1

正常に動作するストアド プロシージャがありますが、その中に 3 つの "select" があります。

選択は内部一時テーブルからではありません。

これは主に手順の形式です。

ALTER PROCEDURE [dbo].[STProce]  
@param1 int,
@param2 int,
@param3 int,
@param4 int,
@param5 int
AS  

select @param1 as p1, @param2 as p2, @param3 as p3

.
.
.

select @param4 as p4

.
.
.

select @param5 as p5

別のプロシージャからプロシージャを実行していて、そこでキャッチする必要があります。

次のように、テーブルを作成し、プロシージャから「exec」を挿入します。

CREATE TABLE #stalledp
(
   RowNumber INT,
   fldid INT,
   fldLastUpdated datetime,
   fldCreationDate datetime,
   fldName nvarchar(255),
   fldPending nvarchar(255)
)

INSERT INTO #stalledp (RowNumber,fldid,fldLastUpdated,fldCreationDate,fldName,fldPending)
EXEC spDebuggerViews_GetStuckWorkflowInstances @workflowSpaceId='00000000-0000-0000-0000-000000000000',@pageNum=1,@pageSize=100000,@orderByColumn=N'fldid',@sortOrder=1,@workflowInstanceId=0,@stuckInstanceType=1,@createdDateFrom='1900-01-01 00:00:00',@createdDateTo='9999-01-01 23:59:59',@updatedDateFrom='1900-01-01 00:00:00',@updatedDateTo='9999-01-01 23:59:59'

その後、次のエラーが表示されます。

Column name or number of supplied values does not match table definition.

テーブルの列の順序と名前は、プロシージャが返すものとまったく同じです。

プロシージャが返すテーブルの 1 つだけをキャッチし、他のテーブルを回避する可能性はありますか? 手続きの変更は一切できません。

プロシージャの最初の選択と同じフィールドをテーブルに宣言しようとしましたが、次のようなエラーが表示されます

前もって感謝します!

4

2 に答える 2

0

返された結果セットがすべて同じ構造である場合は、それらを一時テーブルにダンプできます。ただし、フィールドのデータを使用して特定の行がどの結果セットから来たかを判断できない場合、すべての結果セットが得られ、そうでないものを除外する方法がないため、これだけでは不十分です。欲しいです。

複数の結果セットを個別に操作する唯一の方法は、構造が同じか異なるかに関係なく、アプリ コード (つまり、クライアント接続) を使用することです。別のクエリのコンテキスト内でこれを行う場合は、SQLCLR を使用する必要があります。

以下の C# コードは、4 つの結果セットを返す T-SQL ストアド プロシージャを実行する SQLCLR ストアド プロシージャを示しています。最初の 2 つの結果セットをスキップし、3 番目の結果セットのみを返します。これにより、必要に応じて SQLCLR ストアド プロシージャを INSERT...EXEC で使用できます。

次のコードによって呼び出される T-SQL ストアド プロシージャのコードは、C# コード ブロックの下に示されています。T-SQL テスト プロシージャが実行sp_who2され、そのプロシージャによって返されるフィールドのサブセットのみが返されます。これは、読み取っているものとまったく同じ結果セットを返す必要がないことを示しています。輸送中に操作できます。

C# SQLCLR プロシージャ:

using System;
using System.Data;
using System.Data.SqlClient;
using System.Data.SqlTypes;
using Microsoft.SqlServer.Server;

public class TheProc
{
    [Microsoft.SqlServer.Server.SqlProcedure]
    public static void Get3rdResultSetFromGetStuckWorkflowInstances()
    {
        int _ResultSetsToSkip = 2; // we want the 3rd result set

        SqlConnection _Connection = null;
        SqlCommand _Command = null;
        SqlDataReader _Reader = null;

        try
        {
            _Connection = new SqlConnection("Context Connection = true;");
            _Command = _Connection.CreateCommand();

            _Command.CommandType = CommandType.StoredProcedure;
            _Command.CommandText = "tempdb.dbo.MultiResultSetTest";
            // (optional) add parameters (but don't use AddWithValue!)

            // The SqlDataRecord will be used to define the result set structure
            // and act as a container for each row to be returned
            SqlDataRecord _ResultSet = new SqlDataRecord(
                new SqlMetaData[]
                {
                    new SqlMetaData("SPID", SqlDbType.Char, 5),
                    new SqlMetaData("Status", SqlDbType.NVarChar, 30),
                    new SqlMetaData("Login", SqlDbType.NVarChar, 128),
                    new SqlMetaData("HostName", SqlDbType.NVarChar, 128),
                    new SqlMetaData("BlkBy", SqlDbType.VarChar, 5),
                    new SqlMetaData("DBName", SqlDbType.NVarChar, 128)
                });

            SqlContext.Pipe.SendResultsStart(_ResultSet); // initialize result set

            _Connection.Open();

            _Reader = _Command.ExecuteReader();

            // Skip a predefined number of result sets
            for (int _Index = 0;
                     _Index < _ResultSetsToSkip && _Reader.NextResult();
                     _Index++) ;

            // Container used to move 1 full row from the result set being read
            // to the one being sent, sized to the number of fields being read
            Object[] _TempRow = new Object[_Reader.FieldCount];

            while (_Reader.Read())
            {
                _Reader.GetValues(_TempRow);                // read all columns
                _ResultSet.SetValues(_TempRow);             // set all columns
                SqlContext.Pipe.SendResultsRow(_ResultSet); // send row
            }
        }
        catch
        {
            throw;
        }
        finally
        {
            if(SqlContext.Pipe.IsSendingResults)
            {
                SqlContext.Pipe.SendResultsEnd(); // close out result set being sent
            }

            if(_Reader != null && !_Reader.IsClosed)
            {
                _Reader.Dispose();
            }

            _Command.Dispose();

            if (_Connection != null && _Connection.State != ConnectionState.Closed)
            {
                _Connection.Dispose();
            }
        }

        return;
    }
}

T-SQL テスト プロシージャ:

USE [tempdb]
SET ANSI_NULLS ON;
IF (OBJECT_ID('dbo.MultiResultSetTest') IS NOT NULL)
BEGIN
    DROP PROCEDURE dbo.MultiResultSetTest;
END;
GO

CREATE PROCEDURE dbo.MultiResultSetTest
AS
SET NOCOUNT ON;

SELECT 1 AS [ResultSet], 'asa' AS [test];

SELECT 2 AS [ResultSet], NEWID() AS [SomeGUID], GETDATE() AS [RightNow];

EXEC sp_who2;

SELECT 4 AS [ResultSet], CONVERT(MONEY, 131.12) AS [CashYo];
GO

EXEC tempdb.dbo.MultiResultSetTest;

すること:

  • _ResultSetsToSkip適宜調整してください。最初の結果セットのみが必要な場合は、単純に両方_ResultSetsToSkipforループを削除します。

  • _ResultSet適宜定義

  • _Command.CommandText「spDebuggerViews_GetStuckWorkflowInstances」に設定

  • SqlParameter(つまり@workflowSpaceId='00000000-0000-0000-0000-000000000000',@pageNum=1,@pageSize=100000,@orderByColumn=N'fldid',@sortOrder=1,@workflowInstanceId=0,@stuckInstanceType=1,@createdDateFrom='1900-01-01 00:00:00',@createdDateTo='9999-01-01 23:59:59',@updatedDateFrom='1900-01-01 00:00:00',@updatedDateTo='9999-01-01 23:59:59')を介して必要なパラメータを作成します

  • 必要に応じて、SQLCLR プロシージャに入力パラメーターを追加して、特定SqlParameterの s の値を設定するために使用できるようにします。

次に、次のように使用します。

INSERT INTO #stalledp 
         (RowNumber,fldid,fldLastUpdated,fldCreationDate,fldName,fldPending)
EXEC Get3rdResultSetFromGetStuckWorkflowInstances;
于 2015-02-16T17:10:12.723 に答える
-1

最初のレコード セットを取得する方法はありますが、残念ながら他のレコード セットは運が悪いです。

EXEC sp_addlinkedserver @server = 'LOCALSERVER',  @srvproduct = '',
                        @provider = 'SQLOLEDB', @datasrc = @@servername
SELECT * FROM OPENQUERY(LOCALSERVER, 'EXEC testproc2')

編集:列がnullでないことを他の結果セットで確認するだけでよい場合は、次のように予想される結果セットを事前定義できます。

EXEC testproc2 WITH RESULT SETS (
        (a VARCHAR(MAX) NOT NULL, b VARCHAR(MAX) NOT NULL), 
        (a VARCHAR(MAX) NOT NULL)
);

ストアド プロシージャ内のクエリが null 値を返す場合、プロシージャのその時点で例外が発生します。ただし、これはSQL Server 2012以降でのみ機能します。

于 2015-02-15T12:16:53.980 に答える