SQL Server - 事务回滚错误?

时间:2009-11-17 15:38:13

标签: sql sql-server sql-server-2005 transactions

我们有一个客户端应用程序在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;

它由一个长字符串命令发送。

如果其中一个插入失败,或者命令的任何部分失败,SQL Server是否会回滚该事务?如果它没有回滚,我是否必须发送第二个命令才能回滚?

我可以详细介绍我正在使用的api和语言,但我认为SQL Server应该对任何语言都做出相同的反应。

5 个答案:

答案 0 :(得分:186)

您可以在事务之前放置set xact_abort on,以确保sql在出错时自动回滚。

答案 1 :(得分:177)

您是正确的,因为整个交易将被回滚。您应该发出命令将其回滚。

您可以将其包装在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

答案 2 :(得分:28)

此处获取错误消息的代码与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

答案 3 :(得分:21)

来自MDSN文章Controlling Transactions (Database Engine)

  

如果批处理中发生运行时语句错误(例如违反约束),则数据库引擎中的默认行为是仅回滚生成错误的语句。您可以使用SET XACT_ABORT语句更改此行为。执行SET XACT_ABORT ON后,任何运行时语句错误都会导致当前事务的自动回滚。 SET XACT_ABORT不会影响编译错误,例如语法错误。有关更多信息,请参阅SET XACT_ABORT(Transact-SQL)。

在您的情况下,当任何插入失败时,它将回滚整个事务。

答案 4 :(得分:10)

  

如果其中一个插入失败,或者命令的任何部分失败,SQL服务器是否会回滚该事务?

不,它没有。

  

如果它没有回滚,我是否必须发送第二个命令才能回滚?

当然,您应该发出ROLLBACK而不是COMMIT

如果要决定是提交还是回滚事务,则应从语句中删除COMMIT句子,检查插入的结果,然后发出COMMIT或{{1取决于检查的结果。