设置xact_abort并尝试一起捕获

问题描述 投票:6回答:2

我在我的sp中有一个try catch块,在try中只有一个insert语句。如果是pk违规则捕获检查错误代码,如果是则更新。但有时我得到“当前事务无法提交,不能支持写入日志文件的操作。回滚事务。

在批处理结束时检测到不可提交的事务。事务被回滚。“所以我添加了xact_abort,但后来我继续得到”EXECUTE后的事务计数表示BEGIN和COMMIT语句的数量不匹配。“我找到了这个.http://www.ashishsheth.com/post/2009/08/14/Set-XACT_ABORT-ON-and-TryCatch-block-in-Sql-Server-2005.aspx

如果这是真的。如果我的try块中有xact_abort错误,我的catch代码是否会运行?

sql-server try-catch xact-abort
2个回答
12
投票

至少在SQL SERVER 2008中,SET XACT_ABORT ON会导致错误跳过CATCH块,这是不对的:

这是我尝试使用Northwind数据库的代码

SET XACT_ABORT OFF
BEGIN TRY
    SELECT 1,  @@TRANCOUNT
BEGIN TRAN
    UPDATE [dbo].[Categories]
    SET Description='BLAH'
    WHERE [CategoryID]=2
    SELECT 2,  @@TRANCOUNT

    SELECT 1/0 as whoops


COMMIT
    SELECT 3,  @@TRANCOUNT

END TRY
BEGIN CATCH
    SELECT 'In Catch. Error occured', 4,  @@TRANCOUNT

     IF (XACT_STATE()) = 0
    BEGIN
        SELECT
            N'There is no transaction'

    END;


     IF (XACT_STATE()) = -1
    BEGIN
        SELECT
            N'The transaction is in an uncommittable state.' +
            'Rolling back transaction.'
        ROLLBACK TRANSACTION;
    END;

    -- Test whether the transaction is committable.
    IF (XACT_STATE()) = 1
    BEGIN
        SELECT
            N'The transaction is committable.' +
            'Committing transaction.'
        COMMIT TRANSACTION;   
    END;

END CATCH

显然,这会在遇到SELECT 1/0语句时强制出错。使用SET XACT_ABORT OFF时,当到达CATCH块时,XACT_STATE()函数返回的值为1,导致代码运行COMMENT事务。当SET XACT_ABORT打开时,CATCH块中返回的值为-1,因此执行ROLL返回事务的代码。

这基于:

http://msdn.microsoft.com/en-us/library/ms175976.aspx


0
投票

让我补充一点,在那个特定场景中(尝试插入,如果PK违规然后捕获并更新),最好使用IF EXISTS(select ....)来查看行是否存在并将UPDATE语句放在那里。将INSERT语句放在ELSE块中。更清洁。

© www.soinside.com 2019 - 2024. All rights reserved.