web-dev-qa-db-ja.com

SQL Server-トランザクションはエラー時にロールバックしますか?

次のようなSQL Server 2005でSQLを実行しているクライアントアプリがあります。

BEGIN TRAN;
INSERT INTO myTable (myColumns ...) VALUES (myValues ...);
INSERT INTO myTable (myColumns ...) VALUES (myValues ...);
INSERT INTO myTable (myColumns ...) VALUES (myValues ...);
COMMIT TRAN;

1つの長い文字列コマンドによって送信されます。

挿入のいずれかが失敗した場合、またはコマンドの一部が失敗した場合、SQL Serverはトランザクションをロールバックしますか?ロールバックしない場合、ロールバックするために2番目のコマンドを送信する必要がありますか?

使用しているAPIと言語の詳細を指定できますが、SQL Serverはどの言語でも同じように応答するはずです。

177
jonathanpeppers

トランザクションの前にset xact_abort onを置くと、エラーが発生した場合にSQLが自動的にロールバックされるようにできます。

187
user121301

トランザクション全体がロールバックされるという点で正しいです。コマンドを発行してロールバックする必要があります。

次のように、これをTRY CATCHブロックでラップできます。

BEGIN TRY
    BEGIN TRANSACTION

        INSERT INTO myTable (myColumns ...) VALUES (myValues ...);
        INSERT INTO myTable (myColumns ...) VALUES (myValues ...);
        INSERT INTO myTable (myColumns ...) VALUES (myValues ...);

    COMMIT TRAN -- Transaction Success!
END TRY
BEGIN CATCH
    IF @@TRANCOUNT > 0
        ROLLBACK TRAN --RollBack in case of Error

    -- you can Raise ERROR with RAISEERROR() Statement including the details of the exception
    RAISERROR(ERROR_MESSAGE(), ERROR_SEVERITY(), 1)
END CATCH
178
Raj More

MSSQL Server 2016で動作するエラーメッセージを取得するコードは次のとおりです。

BEGIN TRY
    BEGIN TRANSACTION 
        -- Do your stuff that might fail here
    COMMIT
END TRY
BEGIN CATCH
    IF @@TRANCOUNT > 0
        ROLLBACK TRAN

        DECLARE @ErrorMessage NVARCHAR(4000) = ERROR_MESSAGE()
        DECLARE @ErrorSeverity INT = ERROR_SEVERITY()
        DECLARE @ErrorState INT = ERROR_STATE()

    -- Use RAISERROR inside the CATCH block to return error  
    -- information about the original error that caused  
    -- execution to jump to the CATCH block.  
    RAISERROR (@ErrorMessage, -- Message text.  
               @ErrorSeverity, -- Severity.  
               @ErrorState -- State.  
               );
END CATCH
29
samwise

MDSNの記事、 Controlling Transactions(Database Engine) から。

バッチで実行時ステートメントエラー(制約違反など)が発生した場合、データベースエンジンのデフォルトの動作では、エラーを生成したステートメントのみがロールバックされます。この動作は、SET XACT_ABORTステートメントを使用して変更できます。 SET XACT_ABORT ONの実行後、実行時ステートメントエラーが発生すると、現在のトランザクションの自動ロールバックが発生します。構文エラーなどのコンパイルエラーは、SET XACT_ABORTの影響を受けません。詳細については、「SET XACT_ABORT(Transact-SQL)」を参照してください。

あなたの場合、挿入のいずれかが失敗すると、完全なトランザクションがロールバックされます。

21
Vitaly

挿入の1つが失敗した場合、またはコマンドの一部が失敗した場合、SQLサーバーはトランザクションをロールバックしますか?

いいえ、違います。

ロールバックしない場合、ロールバックするために2番目のコマンドを送信する必要がありますか?

もちろん、ROLLBACKの代わりにCOMMITを発行する必要があります。

トランザクションをコミットするかロールバックするかを決定する場合は、ステートメントからCOMMIT文を削除し、挿入の結果を確認してから、チェックの結果に応じてCOMMITまたはROLLBACKを発行する必要があります。

10
Quassnoi