8

開発用PCにSQLServer2012のフルバージョンをインストールしています。

ここでは、データのソースとしてストアドプロシージャを使用して新しい一時テーブルを作成する方法を示す例に従おうとしています。複数のストアドプロシージャの結果を1つの一時テーブルに結合しようとしています(さまざまな結果セットの列構造/定義は同じです)。

配管が機能しているかどうかをテストするために、次のクエリを発行します。

 SELECT * FROM OPENQUERY("FOO\SQL2012", 'exec mySchema.myStoredProc')

しかし、私はその単純な配管テストの選択クエリからこのエラーを受け取ります:

メッセージ11526、レベル16、状態1、プロシージャsp_describe_first_result_set、1行目
ステートメント'insert #tmp(foo1、foo2、foo3)select' O'as foo1、foo2、foo3' inprocedure'myStoredProc'が使用するため、メタデータを決定できませんでした一時テーブル。

エラーを正しく理解している場合、OPENQUERYは、サーバーがデータベース内の永続的な定義から列のデータ型を抽出できるかどうかに依存し、ストアドプロシージャでインスタンス化された一時テーブルは、一時的なものであり、永続的な定義がありません。その場合、OPENQUERYに可能な限り最善を尽くし、列のデータ型をインテリジェントに推測するように指示する設定はありますか?

これが私がテストしているダミーのSPです:

create proc testproc
as
begin

create table #test
(id int, name varchar(5) );

insert into #test(id,name)values(1,'xxx');
select * from #test;
--drop table #test;   -- tried dropping and not dropping, same error either way
end
4

4 に答える 4

13

これを試して:

SELECT *
FROM OPENQUERY("FOO\SQL2012", 'SET FMTONLY OFF; EXEC mySchema.myStoredProc;') X;

これは、リンクサーバー全体でストアドプロシージャを実行するときに、プロバイダーが最初に結果の行セットの形状を決定しようとするためです。これはSET FMTONLY ON;、ステートメントを発行して実行することによって行われます。一時テーブルを使用しないストアドプロシージャでは、これはうまく機能します。クエリパーサーは基本的に、メタデータだけでなく、すべてのデータを実際にフェッチすることなくドライランを実行します(推定実行プランを表示するようなものです)。

問題は、ストアドプロシージャ一時テーブルを使用する場合、一時テーブルのメタデータが存在しないために失敗することです。一時テーブルを使用しないストアドプロシージャで機能するメタ分析では収集できません。SET FMTONLY OFF;したがって、解決策は、ストアドプロシージャを実行しているバッチ内で手動で行うことです。

このメソッドを使用すると、ストアドプロシージャが2回実行されることに注意してください。1回目はメタデータ(破棄されるデータ)を収集し、2回目は実際にデータを返します。呼び出されたストアドプロシージャが特にコストがかかるか、副作用がある場合は、余裕を持たせる必要があります。

最後に、このトリックはすべてのストアドプロシージャで機能するとは限らないことに注意してください。ストアドプロシージャで実行できることは、作業中にレンチを投げるだけです。すべての可能性を知っているわけではありませんが、そのうちの1つは複数のレコードセットを返しています。

SET FMTONLY OFF動作しない更新への応答:一時テーブルを使用しないように、またはセッションキーの永続テーブルを使用するようにSPを再構築できますか?これらのオプションのいずれかがその仕事をすることができます。SQL Server 2012では、テーブル値パラメーターを使用してデータを渡すオプションもあります。

Erland Sommarskogのストアドプロシージャ間でデータを共有する方法を読むと、目的を達成するためのインスピレーションが得られる可能性があります。

于 2013-01-13T02:12:26.173 に答える
4

WITH RESULT SETS [NONE | UNDEFINED]EXEC呼び出しの最後に「」を追加すると、この問題が修正されるはずです。http://technet.microsoft.com/en-us/library/ms188332.aspx

于 2013-11-29T15:47:41.997 に答える
2

リモートプロシージャが結果セットを返す場合は、プロシージャをで開始する必要がありますSET NOCOUNT ON。そうでない場合、最初の結果セットはメタデータのない行数であり、エラーは常に生成されます。

WITH RESULT SETS((field1 type1, field2 type2...))次に、EXECステートメントの最後でを使用して結果セットを定義できます。

(これは質問に直接答えるものではありませんが、ストアドプロシージャが中間結果を格納するための一時テーブルを作成したため、同じエラーが発生しました。)

于 2020-09-03T15:18:01.127 に答える
1

ゲストサーバーspの最初に結果セット(選択クエリ)がない場合、リンクサーバーは結果セットを解析できませんでした。私が使用するオプションは次のとおりです。

create procedure test
as

    if 1=2
    select a, b, c from table

    declare @variable varchar(10)
    ----...and rest of your procedure...

    --in the end
    select a, b, c from table
于 2015-01-15T15:59:29.753 に答える