web-dev-qa-db-ja.com

SQL Serverは、トランザクションに関してストアドプロシージャ内のステートメントをどのように扱いますか?

いくつかの個別のSELECT、INSERT、UPDATE、DELETEステートメントで構成されるストアドプロシージャがあるとします。明示的なBEGIN TRANS/COMMIT TRANS/ROLLBACK TRANSロジックはありません。

SQL Serverはこのストアドプロシージャをトランザクション単位でどのように処理しますか?各ステートメントには暗黙の接続がありますか?または、ストアドプロシージャのトランザクションは1つですか?

また、T-SQLやSQL Server Management Studioを使用して、これを自分でどのように見つけられたのでしょうか。

ありがとう!

44
Sleepless

接続は1つしかありません。これは、ストアドプロシージャ内のSQLコマンドの数に関係なく、プロシージャの実行に使用されます。

ストアドプロシージャに明示的なBEGIN TRANSACTIONがないため、各ステートメントは単独で実行され、エラーが発生した場合に変更をロールバックすることはできません。

ただし、ストアドプロシージャを呼び出す前にBEGIN TRANSACTIONを発行すると、すべてのステートメントがトランザクション内でグループ化され、ストアドプロシージャの実行後にCOMMITまたはROLLBACKすることができます。

ストアドプロシージャ内から、システム変数 @@ TRANCOUNT(Transact-SQL) の値を確認することで、トランザクション内で実行しているかどうかを確認できます。ゼロはトランザクションがないことを意味し、それ以外はトランザクションのネストされたレベルの数を示します。SQLサーバーのバージョンによっては、 XACT_STATE(Transact-SQL) も使用できます。

次の場合:

BEGIN TRANSACTION

EXEC my_stored_procedure_with_5_statements_inside @Parma1

COMMIT

プロシージャ内のすべてがトランザクションによってカバーされ、6つのステートメントすべて(EXECはトランザクションによってカバーされるステートメント、1 + 5 = 6)です。これを行う場合:

BEGIN TRANSACTION

EXEC my_stored_procedure_with_5_statements_inside @Parma1
EXEC my_stored_procedure_with_5_statements_inside @Parma1

COMMIT

2つのプロシージャコール内のすべてがトランザクションによってカバーされ、すべてのステートメントが12です(2つのEXECはどちらもトランザクションによってカバーされるステートメントであり、1 + 5 + 1 + 5 = 12)。

35
KM.

テストテーブルにレコードを挿入するなど、単純なことを行う小さなストアドプロシージャを作成することで、自分で調べることができます。その後、トランを開始します。 sp_testを実行します。ロールバック;新しいレコードはありますか?その場合、SPは外部トランザクションを無視します。そうでない場合、SPはトランザクション内で実行される別のステートメントです(これはケース)。

1
MJB