時々、次のコードスニペットを見ました。 if @@trancount > 0
でbegin try
が必要なのはいつですか?両方?または、チェックの前にロールバックする場合に常にチェックするのは安全な方法(ベストプラクティス)ですか?
begin tran
begin try
... just several lines of sql ...
if @@trancount > 0 commit tran
end try
begin catch
if @@trancount > 0 rollback tran
end catch
@@trancount
を扱うときに考慮すべきいくつかのシナリオを考えることができます。
Remus Rusanuの 例外処理とネストされたトランザクション がこれらすべての可能性を処理すると信じています。
@@ trancountを使用しない場合、ネストされたトランザクションストアドプロシージャのエラーメッセージは、「ロールバックトランザクションリクエストに対応する開始トランザクションがありません」というエラーの正確な原因を返しません。適切な構文でエラーを簡単に処理できます。
質問に答えるには、@@ trancountを実行するのは、中央のコードが開始したトランザクションのコミットまたはロールバックを既に実行している可能性がある場合です。したがって、たとえばストアドプロシージャを呼び出す場合は、最後にチェックを実行します。
ちなみにif @@ trancount> 0を実行するよりも、コードブロックの先頭で@@ trancountを確認し、最後までにカウントが上がっているかどうかを確認することをお勧めします。 try/catchに応じて、コミットまたはロールバックします。
特にトリガーを使用している場合、@@ trancountは常に1になるため、@@ trancount> 0を実行するとエラーが発生する可能性があります。
しかし、コードがストアドプロシージャ内にある場合でも、それ自体がオープントランザクションを持っている別のプロシージャによって呼び出されたと仮定すると、コードにエラーが発生してロールバックすると、外部ストアドプロシージャのトランザクションもロールバックされます( https://www.sqlskills.com/blogs/paul/a-sql-server-dba-myth-a-day-2630-nested-transactions-are-real/ )。
そう
BEGIN TRAN PRINT @@ TRANCOUNT
BEGIN TRAN PRINT @@ TRANCOUNT
ROLLBACK TRAN PRINT @@ TRANCOUNT
1 2 0を示します
基本的に-中央のコードが他のプロシージャを呼び出している場合、IF @@ TRANCOUNTチェックを実行する必要があります。
チェックの理由は、@@ trancount = 0のときにtransをコミットまたはロールバックすると、次のエラーメッセージで例外が発生するためです。COMMITTRANSACTION要求に対応するBEGIN TRANSACTIONがありません。