问题描述
|
我想对此答案进行一些澄清->包含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配对?
-如果这是您想要的行为,是的-这意味着您不会从旧版代码中获得新的行为。
对于遗留代码,这是最安全的方法吗?
-为了最大程度地减少对其他存储过程的影响,是