gpt4 book ai didi

sql-server - 是否只需要在开始事务时调用 SET XACT_ABORT ?

转载 作者:行者123 更新时间:2023-12-04 00:48:14 27 4
gpt4 key购买 nike

我想澄清一下这个答案 -> 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 或整个通话
    堆?
  • 如果我想重构一个 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

    最佳答案

    据我所知,当子批次的执行结束时,它会恢复此设置的先前值。

    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

    关于sql-server - 是否只需要在开始事务时调用 SET XACT_ABORT ?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/5707501/

    27 4 0
    Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
    广告合作:1813099741@qq.com 6ren.com