2011-04-18 41 views
3

我希望得到一些澄清这个答案 - >Nested stored procedures containing TRY CATCH ROLLBACK pattern?只有在启动事务时才需要调用SET XACT_ABORT?

下面是从上面的链接

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, @ErrorMessage, etc] 
END CATCH 
GO 

回答

4

据我可以看到,当一个子批处理的执行结束它恢复此设置的以前的值。

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 
+0

要检查,这是否意味着下面的答案是不正确的(即以我的阅读吉博的答案是矛盾这个答案;但都有upvotes ...假设你是正确的因为你有更高的声誉)。 – JohnLBevan 2015-09-22 19:20:35

+1

@JohnLBevan - 是的。 – 2015-09-22 20:00:49

0

是XACT_ABORT当前PROC活性,或仅在整个调用堆栈? - 当设置为ON时,从该点开始对所有连接都是活动的

如果我想重构proc以使用SET XACT_ABORT ON,是否需要将它与SET XACT_ABORT OFF配对?
- 如果这是你想要的行为,是的 - 这意味着你不会从传统代码中获得新的行为。

这是遗传代码最安全的方法吗? - 为了最大限度地减少对其他存储过程的影响,是的

相关问题