サーバー間のリモート ストアド プロシージャのエラー処理

SQL Server のローカル インスタンスからクライアントに対してリモート ストアド プロシージャやバッチを実行すると、次に示すステートメント中断エラーやバッチ中断エラーが発生することがあります。

  • ステートメント中断エラーが発生した場合、エラーの発生元のステートメントは終了しますが、リモート ストアド プロシージャまたはバッチの実行は続行されます。

  • バッチ中断エラーが発生した場合、リモート ストアド プロシージャまたはバッチ全体の実行が終了します。

  • リモート ストアド プロシージャやバッチを TRY ブロックのスコープ内で実行する場合、バッチ中断エラーを TRY...CATCH 構造を使用して処理できます。

ステートメント中断エラーやバッチ中断エラーが発生した場合のリモート ストアド プロシージャとバッチの動作は、ローカル サーバーの SET XACT_ABORT 設定によって異なります。

SET XACT_ABORT が OFF の場合

ローカル サーバーで SET XACT_ABORT が OFF に設定されている場合、リモート ストアド プロシージャ内のステートメント中断エラーはすべて、ステートメント中断エラーとしてローカル サーバーからクライアントに伝達されます。このとき、エラーの発生元のステートメントだけが終了します。クライアントは、ステートメント中断エラーに対応するエラー メッセージを受け取ります。また、リモート ストアド プロシージャが最後まで実行される場合、@@ERROR は 0 を返します。エラーが TRY ブロックのスコープ内で発生しても、実行が継続され、CATCH ブロックは実行されません。

リモート ストアド プロシージャ内のバッチ中断エラーはすべて、ローカル サーバーからクライアントに伝達されます。リモート ストアド プロシージャを呼び出した EXECUTE ステートメントは終了しますが、EXECUTE ステートメントを含んだバッチやストアド プロシージャの実行は続行します。このため、@@ERROR はリモート ストアド プロシージャを終了させたエラーに対応するエラー コードを返しますが、ストアド プロシージャの戻り値は NULL です。エラーを生成するリモート ストアド プロシージャがローカル サーバー上の TRY ブロックのスコープ内で実行された場合、エラーが発生するとリモート サーバーで発生した最後のエラーに関する情報と共に制御が CATCH ブロックに渡されます。

エラーのトラブルシューティングを行う場合は、TRY...CATCH 構造の TRY ブロック内からリモート ストアド プロシージャを実行します。リモート ストアド プロシージャが正常に完了しない場合は、リモート サーバーで発生した最後のエラーに関する情報と共に、ローカル サーバー上の対応する CATCH ブロックに実行が移動します。リモート ストアド プロシージャが正常に完了すると、ローカル サーバー上の TRY ブロック内で実行が続行するので、リモート ストアド プロシージャの戻り値を使用できます。

また、リモート ストアド プロシージャを TRY ブロックのスコープ外で実行する場合は、リモート ストアド プロシージャの終了時に @@ERROR を調べてそのリモート ストアド プロシージャが完了したかどうかを確認します。@@ERROR が 0 の場合は、リモート ストアド プロシージャは正常に実行されたので、ストアド プロシージャの戻り値を使用できます。@@ERROR が 0 以外の場合は、リモート ストアド プロシージャは正常に完了しなかったので、ストアド プロシージャの戻り値は使用できません。

SET XACT_ABORT が ON の場合

ローカル サーバーで SET XACT_ABORT が ON に設定されている場合は、リンク サーバーにこの設定が伝達されます。リモート ストアド プロシージャのすべてのステートメント中断エラーとバッチ中断エラーが、ローカル サーバーでバッチ中断エラーに変換されます。したがって、リモート ストアド プロシージャを呼び出したバッチまたはストアド プロシージャの実行は、リモート ストアド プロシージャと共に終了します。エラーを生成するリモート ストアド プロシージャがローカル サーバー上の TRY ブロックのスコープ内で実行された場合、エラーが発生するとリモート サーバーで発生した最後のエラーに関する情報と共に制御が CATCH ブロックに渡されます。

リモート ストアド プロシージャを TRY ブロックのスコープ外で実行すると、EXECUTE ステートメントの後のステートメントは実行されないので、@@ERROR を調べてバッチ エラーが発生したことを確認することはできません。このため、リモート ストアド プロシージャは TRY...CATCH 構造の TRY ブロック内から実行する必要があります。リモート ストアド プロシージャが正常に完了しない場合は、リモート サーバーで発生した最後のエラーに関する情報と共に、ローカル サーバー上の対応する CATCH ブロックに実行が移動します。リモート ストアド プロシージャが正常に完了した場合は、ローカル サーバー上の TRY ブロック内で実行が続行されるので、リモート ストアド プロシージャの戻り値を使用できます。

RAISERROR と TRY...CATCH

重大度が 20 未満の RAISERROR をリモート ストアド プロシージャ内から呼び出すと、リモート サーバーでステートメント中断エラーが発生します。ローカル サーバー上の TRY...CATCH 構造では、リモート バッチ中断エラーだけが処理されます。ローカル サーバー上の TRY ブロックのスコープ内で、リモート ストアド プロシージャにより重大度が 20 未満の RAISERROR が呼び出された場合、制御は TRY...CATCH 構造の CATCH ブロックには渡されません。ただし、リモート サーバー上の RAISERROR の重大度が 20 以上の場合は、接続が切断されて、ローカル サーバー上の実行が CATCH ブロックに渡されます。