设置xact_abort并尝试一起捕获

时间:2013-04-05 16:59:10

标签: sql-server try-catch xact-abort

我在我的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代码是否会运行?

2 个答案:

答案 0 :(得分: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

答案 1 :(得分:0)

让我补充一点,在特定情况下(尝试插入,如果PK违反则捕获并更新),最好使用IF EXISTS(选择...)来查看该行是否存在并将您的那里有UPDATE语句。将您的INSERT语句放在ELSE块中。更清洁。