ストアド プロシージャとトリガでのロールバックとコミット

ストアド プロシージャまたはトリガ内で Transact-SQL ステートメントの ROLLBACK TRANSACTION または COMMIT TRANSACTION を実行できますが、エラーが発生することがあります。

ストアド プロシージャ内

@@TRANCOUNT の値がストアド プロシージャの実行開始時と、プロシージャの完了時とで異なる場合、情報エラー 266 が発生します。この問題は、次の 2 つの状況で発生します。

  • 1 より大きい @@TRANCOUNT でストアド プロシージャが呼び出され、ストアド プロシージャで ROLLBACK TRANSACTION ステートメントが実行された。@@TRANCOUNT が 0 に減少し、ストアド プロシージャが完了するときにエラー 266 が発生します。

  • 1 より大きい @@TRANCOUNT でストアド プロシージャが呼び出され、ストアド プロシージャによって COMMIT TRANSACTION ステートメントが実行された。@@TRANCOUNT が 1 減少し、ストアド プロシージャが完了するときにエラー 266 が発生します。ただし、COMMIT TRANSACTION の後で BEGIN TRANSACTION が実行されると、エラーは発生しません。

トリガ内

トリガは、トリガの実行時に有効な未完了のトランザクションが存在するかのように動作します。このことは、トリガを起動したステートメントが暗黙のトランザクション内にある場合にも明示的なトランザクション内にある場合にもあてはまります。

ステートメントの実行を自動コミット モードで開始する場合、暗黙の BEGIN TRANSACTION が存在するので、エラーが検出されると、そのステートメントが生成したすべての変更を復旧できます。この暗黙のトランザクションは、バッチ内の他のステートメントには影響しません。ステートメントの完了時にこのトランザクションはコミットまたはロールバックされるためです。ただし、トリガが呼び出された時点では、この暗黙のトランザクションはまだ有効です。

トリガが実行されるときに、暗黙のトランザクションが開始されます。トリガの実行が完了して @@TRANCOUNT = 0 になると、エラー 3609 が発生して、バッチが終了します。トリガで BEGIN TRANSACTION ステートメントが実行されると、入れ子になったトランザクションが作成されます。この状況では、COMMIT TRANSACTION ステートメントの実行時に、入れ子になったトランザクションにのみそのステートメントが適用されます。

トリガで ROLLBACK TRANSACTION を使用するときは、次の動作に注意してください。

  • 現在のトランザクションのその時点までに加えられたすべてのデータ変更 (トリガによって行われた変更も含む) がロールバックされます。

  • ROLLBACK ステートメントの実行後、トリガは残りのすべてのステートメントを継続して実行します。これらのステートメントのいずれかがデータを変更する場合、その変更はロールバックされません。

  • トリガ内の ROLLBACK は、トリガを起動したステートメントが入っているバッチ内で宣言され、開かれたすべてのカーソルを閉じて割り当てを解除します。これには、トリガを起動したバッチが呼び出したストアド プロシージャ内で宣言され、開かれたカーソルも含まれます。トリガを起動したバッチの前のバッチで宣言されたカーソルは閉じられるだけです。ただし、次の場合、STATIC カーソルまたは INSENSITIVE カーソルは開かれたままになります。

    • CURSOR_CLOSE_ON_COMMIT が OFF に設定されている。

    • 静的カーソルが同期カーソルであるか、完全にデータが設定された非同期カーソルである。

ROLLBACK TRANSACTION を使用する代わりに、SAVE TRANSACTION ステートメントを使用して、トリガ内で部分的なロールバックを実行できます。