9

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

在批处理结束时检测到不可提交的事务。事务已回滚。”所以我添加了 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

如果这是真的。如果打开 xact_abort 的 try 块中出现错误,我的 catch 代码会不会运行?

4

2 回答 2

15

至少在 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,从而导致运行提交事务的代码。当 SET XACT_ABORT 开启时,在 CATCH 块中返回的值为 -1,因此执行回滚事务的代码。

这是基于:

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

于 2013-04-05T19:10:03.283 回答
0

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

于 2019-04-30T18:25:51.153 回答