ストアド プロシージャ内からの結果セットへのアクセス Transact-SQL SQL Server

StackOverflow https://stackoverflow.com/questions/58940

  •  09-06-2019
  •  | 
  •  

質問

SQL Server 2005 を使用していますが、transact-sql 内からさまざまな結果セットにアクセスする方法を知りたいです。次のストアド プロシージャは 2 つの結果セットを返します。たとえば、別のストアド プロシージャからこれらの結果セットにアクセスするにはどうすればよいですか?

CREATE PROCEDURE getOrder (@orderId as numeric) AS
BEGIN   
    select order_address, order_number from order_table where order_id = @orderId
    select item, number_of_items, cost from order_line where order_id = @orderId
END

両方の結果セットを個別に反復処理できる必要があります。

編集:質問を明確にするために、ストアド プロシージャをテストしたいと思います。VB.NET クライアントから使用されるストアド プロシージャのセットがあり、複数の結果セットを返します。これらはテーブル値関数に変更される予定はなく、実際にはプロシージャをまったく変更することはできません。手順を変更するという選択肢はありません。

プロシージャによって返される結果セットは、同じデータ型または列数ではありません。

役に立ちましたか?

解決

短い答えは次のとおりです。それはできません。

他の人が提案したように、ストアド プロシージャを変更せずに、T-SQL からネストされたストアド プロシージャ呼び出しの複数の結果にアクセスする方法はありません。

完了するには、プロシージャが単一の結果を返す場合、次の構文を使用してその結果を一時テーブルまたはテーブル変数に挿入できます。

INSERT INTO #Table (...columns...)
EXEC MySproc ...parameters...

複数の結果を返すプロシージャに同じ構文を使用できますが、最初の結果のみが処理され、残りは破棄されます。

他のヒント

内部データセットを含む SQL2005 CLR ストアド プロシージャを作成することで、これを簡単に行うことができました。

新しい SqlDataAdapter は、デフォルトで複数の結果セットの sproc を複数のテーブル データセットに .Fill します。これらのテーブルのデータは、書き込みたい呼び出し側 sproc の #Temp テーブルに挿入できます。 データセット.ReadXmlSchema 各結果セットのスキーマが表示されます。

ステップ1:複数の結果セット sproc からデータを読み取る sproc の作成を開始します。

a.スキーマに従って、結果セットごとに個別のテーブルを作成します。

CREATE PROCEDURE [dbo].[usp_SF_Read] AS
SET NOCOUNT ON;
CREATE TABLE #Table01 (Document_ID VARCHAR(100)
  , Document_status_definition_uid INT
  , Document_status_Code VARCHAR(100) 
  , Attachment_count INT
  , PRIMARY KEY (Document_ID));

b.この時点で、ここで作成する CLR sproc を繰り返し呼び出すためにカーソルを宣言する必要がある場合があります。

ステップ2:CLR Sproc を作成する

Partial Public Class StoredProcedures
    <Microsoft.SqlServer.Server.SqlProcedure()> _
    Public Shared Sub usp_SF_ReadSFIntoTables()

    End Sub
End Class

a.を使用して接続します New SqlConnection("context connection=true").

b.複数の結果セットの sproc を含むコマンド オブジェクト (cmd) を設定します。

c.以下を使用してすべてのデータを取得します。

    Dim dataset As DataSet = New DataSet
    With New SqlDataAdapter(cmd)
        .Fill(dataset) ' get all the data.
    End With
'you can use dataset.ReadXmlSchema at this point...

d.各テーブルを反復処理し、すべての行を適切な一時テーブル (上記の手順 1 で作成したテーブル) に挿入します。

最後のメモ:私の経験では、各レコードがどのバッチから来たのかを知るために、テーブル間の関係を強制したい場合があります。

以上です!

~ ショーン、シアトル近郊

あなたにもできるずるいことがあります。オプションのパラメーター N int を sproc に追加します。N の値のデフォルトは -1 です。N の値が -1 の場合は、すべての選択を実行します。それ以外の場合は、N 番目の選択を実行し、N 番目の選択のみを実行します。

例えば、

if (N = -1 or N = 0)
    select ...

if (N = -1 or N = 1)
    select ...

N を指定しない sproc の呼び出し元は、複数のテーブルを含む結果セットを取得します。これらのテーブルの 1 つ以上を別の sproc から抽出する必要がある場合は、N の値を指定して sproc を呼び出すだけです。抽出するテーブルごとに sproc を 1 回呼び出す必要があります。結果セットから複数のテーブルが必要な場合は非効率ですが、純粋な TSQL では機能します。

INSERT INTO ... には文書化されていない追加の制限があることに注意してください。EXEC ステートメント:入れ子にすることはできません。つまり、EXEC が呼び出すストアド プロシージャ (または EXEC が次に呼び出すストアド プロシージャ) 自体は INSERT INTO ... を実行できません。執行。結果を蓄積するプロセスごとに 1 つのスクラッチパッドがあるようです。これらがネストされている場合、呼び出し元がこれを開いて、呼び出し先が再度開こうとするとエラーが発生します。

Matthieu、結果の「タイプ」ごとに個別の一時テーブルを維持する必要があります。また、同じものを複数回実行する場合は、その結果に列を追加して、どの呼び出しによるものかを示す必要がある場合があります。

残念ながらこれを行うことは不可能です。もちろん、問題は、それを許可する SQL 構文がないことです。もちろん、これは「内部」で行われますが、TSQL ではこれらの他の結果を取得することはできず、ODBC などを介してアプリケーションからのみ取得できます。

ほとんどのことと同様、それを回避する方法があります。秘訣は、TSQL でオレオートメーションを使用して ADODB オブジェクトを作成し、各結果セットを順番に開き、指定したテーブルに結果を書き込むことです (または、結果セットに対して任意の処理を実行します)。痛みを楽しむならDMOでもできます。

これを簡単に行うには 2 つの方法があります。結果を一時テーブルに貼り付けてから、sproc から一時テーブルを参照します。もう 1 つの方法は、OUTPUT 変数として使用される XML 変数に結果を入れることです。

ただし、これらのオプションの両方に長所と短所があります。一時テーブルの場合、プロシージャを変更する前に、呼び出しプロシージャを作成するコードをスクリプトに追加して一時テーブルを作成する必要があります。また、手順の最後に一時テーブルをクリーンアップする必要があります。

XML を使用すると、メモリが大量に消費され、処理が遅くなる可能性があります。

それらを一時テーブルに選択するか、テーブル値関数を作成して結果セットを返すことができます。結果セットを反復処理する方法を知りたいですか?

ライセンス: CC-BY-SA帰属
所属していません StackOverflow
scroll top