您仅在开始交易时才需要调用SET XACT_ABORT吗?

问题描述

| 我想对此答案进行一些澄清->包含TRY CATCH ROLLBACK模式的嵌套存储过程? 下面是上面链接代码示例
 1 CREATE PROCEDURE [Name]
 2 AS
 3 SET XACT_ABORT,NOCOUNT ON
 4
 5 DECLARE @starttrancount int
 6
 7 BEGIN TRY
 8    SELECT @starttrancount = @@TRANCOUNT
 9
10    IF @starttrancount = 0
11        BEGIN TRANSACTION
12
13       [...Perform work,call nested procedures...]
14
15    IF @starttrancount = 0 
16        COMMIT TRANSACTION
17 END TRY
19 BEGIN CATCH
20    IF XACT_STATE() <> 0 AND @starttrancount = 0 
21        ROLLBACK TRANSACTION
22    RAISERROR [rethrow caught error using @ErrorNumber,@ErrorMessage,etc]
23 END CATCH
24 GO
假设是从旧式存储过程中调用它来启动事务的。 在这种情况下,此proc将不会自行启动事务,但会更改该调用的XACT_ABORT状态。 所以,我在这里有几个问题。 当前的XACT_ABORT是否处于活动状态 仅proc或整个通话 堆? 如果我想重构要使用的proc SET XACT_ABORT ON,我需要配对吗 SET XACT_ABORT OFF设置吗?对于遗留代码,这是最安全的方法吗? 以下是修改后的示例,该示例有条件地打开XACT_ABORT并将其配对并在proc出口将其关闭
CREATE PROCEDURE [Name]
AS
SET NOCOUNT ON

DECLARE @starttrancount int

BEGIN TRY
   SELECT @starttrancount = @@TRANCOUNT

   IF @starttrancount = 0
   BEGIN
      SET XACT_ABORT ON
      BEGIN TRANSACTION
   END

      [...Perform work,call nested procedures...]

   IF @starttrancount = 0 
   BEGIN
      COMMIT TRANSACTION
      SET XACT_ABORT OFF
   END
END TRY
BEGIN CATCH
   IF XACT_STATE() <> 0 AND @starttrancount = 0 
   BEGIN
       ROLLBACK TRANSACTION
       SET XACT_ABORT OFF
   END
   RAISERROR [rethrow caught error using @ErrorNumber,etc]
END CATCH
GO

解决方法

据我所知,当子批处理的执行结束时,它将恢复该设置的先前值。
SET NOCOUNT ON;

BEGIN TRAN

SELECT CASE
         WHEN 16384 & @@OPTIONS = 16384
           THEN \'XACT_ABORT IS ON\'
         ELSE \' XACT_ABORT IS OFF\'
       END

CREATE TABLE #T
  (
     C INT
  )

SET XACT_ABORT OFF

INSERT INTO #T
VALUES      (1)

EXEC (\'SET XACT_ABORT ON; 
      INSERT INTO #T VALUES(2);
        SELECT CASE
                    WHEN 16384 & @@OPTIONS = 16384
                    THEN \'\'XACT_ABORT IS ON\'\'
                    ELSE \'\' XACT_ABORT IS OFF\'\'
                END 
      \')


INSERT INTO #T
VALUES      (1 / 0)

/*If XACT_ABORT was on we would never get here but we do!*/
COMMIT

SELECT *
FROM   #T

DROP TABLE #T

SELECT CASE
         WHEN 16384 & @@OPTIONS = 16384
           THEN \'XACT_ABORT IS ON\'
         ELSE \' XACT_ABORT IS OFF\'
       END 
退货
------------------
 XACT_ABORT IS OFF


------------------
XACT_ABORT IS ON

Msg 8134,Level 16,State 1,Line 31
Divide by zero error encountered.
The statement has been terminated.
C
-----------
1
2


------------------
 XACT_ABORT IS OFF
,XACT_ABORT是否仅对当前proc或整个调用堆栈有效? -设置为ON时,从该点开始对所有连接均处于活动状态 如果我想重构一个过程以使用SET XACT_ABORT ON,是否需要将其与SET XACT_ABORT OFF配对? -如果这是您想要的行为,是的-这意味着您不会从旧版代码中获得新的行为。 对于遗留代码,这是最安全的方法吗? -为了最大程度地减少对其他存储过程的影响,是

相关问答

Selenium Web驱动程序和Java。元素在(x,y)点处不可单击。其...
Python-如何使用点“。” 访问字典成员?
Java 字符串是不可变的。到底是什么意思?
Java中的“ final”关键字如何工作?(我仍然可以修改对象。...
“loop:”在Java代码中。这是什么,为什么要编译?
java.lang.ClassNotFoundException:sun.jdbc.odbc.JdbcOdbc...