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のコンテキストでそのストアドプロシージャを呼び出そうとすると、エラーが発生します。見て。

どのように修正しますか?

  1. 内部のINSERT...EXECを取得して、これにコードをインライン化するだけです。単一のストアドプロシージャ。ただし、他の手順があるのではないかと思います。つまり、コードをDRYに保つためです。

  2. これはGetプロシージャ、うまくいけば、呼び出しスタックのどこでもデータ操作が発生しません。子プロシージャをテーブル値関数に変換できます。これにより、その内部のINSERT...EXECを変換できます。 INSERT...SELECTに挿入し、この問題を解決します。

  3. 外部プロシージャにスコープされた一時テーブルを使用して、プロシージャ間でデータを渡します。複雑なので、これは私のお気に入りではありません。一般的に、より良いオプションがある場合はこのパターンをお勧めしませんが、完全を期すために、ここに含めます。基本的に、spGetSitesの外部で#tempテーブルを作成する場合は、spGetSitesの内部で(内部で作成せずに)使用できます。データが挿入されていると、プロシージャの実行後も存続し、機能し続けます。

オプション3は、誰もが参加してコーディングに精通していない限り、将来誰かがそれを台無しにするのに十分なほど複雑なコーディングパターンであるため、好きではありません。パターン:*最初にテーブルを作成しない限り、spGetSitesは失敗します。すべての呼び出し元は、最初にまったく同じテーブルを作成することを覚えておく必要があります。 * spGetSitesは、テーブルが空であると想定できません。外部呼び出しからの既存のデータ(または同じ呼び出し元からの以前の実行)が含まれている可能性があります*トラブルシューティングとデバッグ(さらにはクエリプラン)spGetSitesの場合、テーブル作成が混乱するため、より複雑になります。

どうすればよいですか?

複雑さを知らずにコードがspGetSitesの背後にあるので、内側のINSERT...EXECINSERT...SELECTまたは場合によってはすべてのspGetSitesを簡略化/書き換えて、INSERT...EXEC

なしで自己完結型にすることができます。 div>

コメントを残す

メールアドレスが公開されることはありません。 * が付いている欄は必須項目です