事务在违反唯一约束后仍然提交

时间:2015-09-18 13:05:58

标签: sql sql-server tsql

我有一个采用这种格式的存储过程(简化):

SET XACT_ABORT ON
GO
BEGIN TRY
BEGIN TRANSACTION myTransaction
--multiple CRUD operations
--insert statement inserts records into table with unique constraint.

    IF (XACT_STATE()) = 1
      BEGIN     
        COMMIT TRANSACTION myTransaction
        RAISERROR ('TRANSACTION COMMITTED', 0, 1) WITH NOWAIT
        RETURN 1
      END
END TRY

BEGIN CATCH
    IF (XACT_STATE()) = -1
      BEGIN
        SELECT
            ERROR_NUMBER() AS ErrorNumber,
            ERROR_SEVERITY() AS ErrorSeverity,
            ERROR_STATE() AS ErrorState,
            ERROR_PROCEDURE() AS ErrorProcedure,
            ERROR_LINE() AS ErrorLine,
            ERROR_MESSAGE() AS ErrorMessage

        ROLLBACK TRANSACTION myTransaction
        RAISERROR ('TRANSACTION ROLLED BACK', 0, 1) WITH NOWAIT
        RETURN 0
      END
    IF (XACT_STATE()) = 1
      BEGIN         
        COMMIT TRANSACTION myTransaction
        RAISERROR ('TRANSACTION COMMITTED', 0, 1) WITH NOWAIT
        RETURN 1
      END
END CATCH

我试图解决SP尝试将记录插入具有唯一约束的表中的问题,但它失败了,因此它不会插入任何内容。问题是,这似乎不会触发catch块,或者更改XACT_STATE()以反映出存在问题。我究竟做错了什么?

所需的功能是,如果违反约束,整个事务将失败并回滚。

2 个答案:

答案 0 :(得分:6)

当您正在使用

Set Xact_Abort On

我的理解是,当您到达任何Catch部分时,事务已经回滚。没有什么可以回滚的。

还有一些我似乎记得的事情,有时候这样的实例会完全绕过Catch。

答案 1 :(得分:4)

你已经完成了一个相当简单的任务,我只是完全废弃了XACT_ABORT()函数并且只是坐下来试试.catch块。类似......

BEGIN TRY
         BEGIN TRANSACTION myTransaction
--multiple CRUD operations
--insert statement inserts records into table with unique constraint.


-- if an error occurs in any of the above statements the control will
-- jump to Catch block and the Commit trans never gets executed
        COMMIT TRANSACTION myTransaction

END TRY

BEGIN CATCH
  IF @@TRANCOUNT > 0
    BEGIN
       ROLLBACK TRANSACTION myTransaction
    END

        SELECT
            ERROR_NUMBER() AS ErrorNumber,
            ERROR_SEVERITY() AS ErrorSeverity,
            ERROR_STATE() AS ErrorState,
            ERROR_PROCEDURE() AS ErrorProcedure,
            ERROR_LINE() AS ErrorLine,
            ERROR_MESSAGE() AS ErrorMessage

END CATCH