web-dev-qa-db-ja.com

try catchブロックで@@ trancount> 0を確認する必要がある場合

時々、次のコードスニペットを見ました。 if @@trancount > 0begin 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
20
ca9163d9

@@trancountを扱うときに考慮すべきいくつかのシナリオを考えることができます。

  1. 現在のトランザクションは、独自のトランザクションを持つ別のストアドプロシージャから呼び出されました
  2. 現在のトランザクションは、独自のトランザクションを持ついくつかの.NETコードによって呼び出されました
  3. 現在のトランザクションが唯一のトランザクションです

Remus Rusanuの 例外処理とネストされたトランザクション がこれらすべての可能性を処理すると信じています。

8
8kb

@@ trancountを使用しない場合、ネストされたトランザクションストアドプロシージャのエラーメッセージは、「ロールバックトランザクションリクエストに対応する開始トランザクションがありません」というエラーの正確な原因を返しません。適切な構文でエラーを簡単に処理できます。

1
Khati Lx

質問に答えるには、@@ 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チェックを実行する必要があります。

1
John Mann

チェックの理由は、@@ trancount = 0のときにtransをコミットまたはロールバックすると、次のエラーメッセージで例外が発生するためです。COMMITTRANSACTION要求に対応するBEGIN TRANSACTIONがありません。

0
khaled tarboosh