我想澄清一下这个答案 - > Nested stored procedures containing TRY CATCH ROLLBACK pattern?
以下是上述链接中的代码示例
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出口处将其关闭
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
答案 0 :(得分: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
答案 1 :(得分:0)
XACT_ABORT仅对当前proc或整个调用堆栈有效吗? - 当设置为ON时,从该点开始对所有连接都是活动的
如果我想重构一个proc以使用SET XACT_ABORT ON,我是否需要将它与SET XACT_ABORT OFF配对?
- 如果这是你想要的行为,是的 - 这意味着你没有从遗留代码中获得新的行为。
对遗留代码来说,这是最安全的方法吗? - 为了最小化对其他存储过程的影响,是
答案 2 :(得分:0)
在我看来,它仅适用于SET
的存储过程,并在以下时间重置:
如果SET语句在存储过程或触发器中运行,则在存储过程或触发器返回控制之后,将恢复SET选项的值。另外,如果您在通过使用sp_executesql或EXECUTE运行的动态SQL字符串中指定SET语句,则在控制从动态SQL字符串中指定的批处理返回后,将恢复SET选项的值。
从该页面我还不清楚嵌套proc中的行为是什么。