SiteName、SiteId、およびUnitCountの3つの列を返すストアドプロシージャspGetSitesがあります。ストアドプロシージャは完全に正常に実行されます。ストアドプロシージャの結果を一時テーブル@Siteに格納して、以下の構文でレポートに使用しようとしています。今回は、「INSERTEXECステートメントをネストできません」というエラーメッセージが表示されました。
INSERTステートメントとEXECステートメントを同時に使用することはできませんか?
DECLARE @Site TABLE (SiteName VARCHAR(100), SiteId INT, UnitCount INT) INSERT INTO @Site EXEC spGetSites @SiteId = 0
コメント
- 必要があります、 dbfiddle.uk/ … ストアドプロシージャを質問に追加し、SQLServerのバージョンにタグを付けてください。
回答
spGetSites
のコードを見るとプロシージャ、そのプロシージャのどこかに別のINSERT...EXEC
があります。それは、そのプロシージャに直接ある場合もあれば、呼び出す他のプロシージャの腸にネストされている場合もあります。
最終的には、ストアドプロシージャがINSERT...EXEC
を使用している場合、別のINSERT...EXEC
のコンテキストでそのストアドプロシージャを呼び出そうとすると、エラーが発生します。見て。
どのように修正しますか?
-
内部の
INSERT...EXEC
を取得して、これにコードをインライン化するだけです。単一のストアドプロシージャ。ただし、他の手順があるのではないかと思います。つまり、コードをDRYに保つためです。 -
これは
Get
プロシージャ、うまくいけば、呼び出しスタックのどこでもデータ操作が発生しません。子プロシージャをテーブル値関数に変換できます。これにより、その内部のINSERT...EXEC
を変換できます。INSERT...SELECT
に挿入し、この問題を解決します。 -
外部プロシージャにスコープされた一時テーブルを使用して、プロシージャ間でデータを渡します。複雑なので、これは私のお気に入りではありません。一般的に、より良いオプションがある場合はこのパターンをお勧めしませんが、完全を期すために、ここに含めます。基本的に、
spGetSites
の外部で#tempテーブルを作成する場合は、spGetSites
の内部で(内部で作成せずに)使用できます。データが挿入されていると、プロシージャの実行後も存続し、機能し続けます。
オプション3は、誰もが参加してコーディングに精通していない限り、将来誰かがそれを台無しにするのに十分なほど複雑なコーディングパターンであるため、好きではありません。パターン:*最初にテーブルを作成しない限り、spGetSites
は失敗します。すべての呼び出し元は、最初にまったく同じテーブルを作成することを覚えておく必要があります。 * spGetSites
は、テーブルが空であると想定できません。外部呼び出しからの既存のデータ(または同じ呼び出し元からの以前の実行)が含まれている可能性があります*トラブルシューティングとデバッグ(さらにはクエリプラン)spGetSites
の場合、テーブル作成が混乱するため、より複雑になります。
どうすればよいですか?
複雑さを知らずにコードがspGetSites
の背後にあるので、内側のINSERT...EXEC
をINSERT...SELECT
または場合によってはすべてのspGetSites
を簡略化/書き換えて、INSERT...EXEC
なしで自己完結型にすることができます。 div>