SQL Server 2008(2014年も同様)。出力パラメータを持つプロシージャを考えてみましょう。この手順ではエラーが発生する可能性があります(次の例ではエラーが発生します)。 TRY
/CATCH
ブロック内でプロシージャを呼び出す場合、出力パラメーターの動作は同じではないことに注意してください。
例:
create procedure test_output @result varchar(10) output
as
begin
set @result = 'hello'
raiserror('This is an error', 16,1)
set @result = 'error'
end
手順を簡単な方法で起動した場合:
declare @res1 varchar(10)
exec test_output @result = @res1 out
print 'Result is: '+ isnull(@res1, 'empty')
私たちは得ます(そして私はそれで大丈夫です):
メッセージ50000、レベル16、状態1、プロシージャtest_output、行7 [バッチ開始行12]
これはエラーです
結果は次のとおりです:エラー
プロシージャがtry/catchブロックにある場合:
declare @res2 varchar(10)
declare @error_message varchar(max)
begin try
exec test_output @result = @res2 out
end try
begin catch
set @error_message = error_message()
raiserror(@error_message, 16,1)
print 'Result is: '+ isnull(@res2, 'empty')
end catch
私たちは(そして私は動揺しています):
メッセージ50000、レベル16、状態1、行28
これはエラーです
結果は空です
エラーメッセージは問題ありませんが、出力パラメーターは[〜#〜] null [〜#〜]になりました。場合、TRY...CATCH
コンテキスト、実行はRAISERROR
の直後に停止します。出力値がhelloに設定されることを期待していました。
なぜそうなのですか?
そのテストセットアップは順調にスタートしましたが、実際に何が起こっているのかを誤解させる原因となる何かが欠けています。ストアドプロシージャの最初、中間、および最後にPRINT
ステートメントを入力すると、追加の出力により、ここで何が行われているのかが明確になります。例えば:
USE [tempdb];
GO
CREATE PROCEDURE test_output
(
@Result VARCHAR(10) OUTPUT
)
AS
BEGIN
SET NOCOUNT ON;
SET @Result = 'hello';
PRINT 1;
RAISERROR('This is an error', 16, 1);
PRINT 2;
SET @Result = 'error';
PRINT 3;
END;
GO
最初のテストクエリの出力は次のとおりです。
1
Msg 50000, Level 16, State 1, Procedure test_output, Line xxxx [Batch Start Line yyyyy]
This is an error
2
3
Result is: error
そして、それはおそらくあなたがとにかく期待していたことです。しかし、2番目のテストクエリの出力は次のとおりです。
1
Msg 50000, Level 16, State 1, Line xxxxx
This is an error
Result is: empty
それはかなり異なります。 TRY...CATCH
構文内で、RAISERROR
が呼び出されると(つまり、バッチ中止イベントになると)実行が停止されていることがわかります即時。一方、RAISERROR
は、TRY...CATCH
構文内で呼び出されない場合、実行をすぐに停止しません。
ただし、質問の更新で指摘したように、OUTPUT
パラメータがhello
に設定されない理由はこれで説明されません。これは、通常のストアドプロシージャの動作がnotに意図されているためです(バッチ中止エラーのため)部分的な実行を反映します。これについては、次のブログ投稿で説明されています。
意味:ストアドプロシージャが変数をhello
に設定するステップを実行した場合でも、TRY...CATCH
構造内で呼び出されたRAISERROR
はバッチ中止エラーとなり、ストアドプロシージャパラメータが中止された場合、パラメータへの変更は反映されません。
この動作は、次の説明の中心にもあります。