【问题标题】:T-SQL Stored Proc Update not Happening with trigger触发器未发生 T-SQL 存储过程更新
【发布时间】:2020-10-09 16:02:47
【问题描述】:

我在表上使用更新后触发器纯粹是为了测试目的,以便强制 SSIS 包出错。它基本上只是一个触发器,在更新发生后使用静态消息调用RAISERROR()

这在大多数情况下都可以正常工作。但是,当我调用包含 try/catch(不涉及显式事务)的特定存储过程并更新表时,更新不会发生或以某种方式回滚。我对 Try/Catch 的理解是,除非您明确实现 BEGIN/COMMIT/ROLLBACK TRANSACTION,否则它不会回滚。

我似乎误解了 Try/Catch,或者我误解了触发器的功能。我通常尽量不使用触发器,但对于这个用例来说它是有意义的。

如果我注释掉 Try/Catch,一切都会按我的预期运行。

CREATE PROCEDURE dbo.MySproc
AS
BEGIN
    SET NOCOUNT ON;

    BEGIN TRY

        UPDATE dbo.MyTableToFireTrigger SET SomeColumn = 1 WHERE SomeColumn = 0

    END TRY
    BEGIN CATCH
        --I'm able to log the after update trigger error message here, but it seems to be rolling back the update.
    END CATCH;
END

触发器创建:

CREATE TRIGGER dbo.MyTrigger ON dbo.MyTableToCauseTrigger
        AFTER UPDATE
        AS
        BEGIN
          RAISERROR('Error', 16, 1);
        END;

【问题讨论】:

  • 为什么要使用RAISERROR(),至少从 SQL Server 2012 开始就已经推荐了THROW(包括在文档中)。至于为什么它不起作用,请花时间向我们提供minimal reproducible example。例如,我们这里没有触发器或表的 DDL。
  • 这只是为了测试目的,可能永远不会再使用了。如果 RAISERROR() 导致我的问题而 THROW 不会有特定原因,我很想听听。
  • 这不需要最小的可重现示例。这只是功能问题。代码没有损坏,它适用于没有 Try/Catch 的存储过程,如果我删除 Try/Catch,它也适用于这个存储过程。我敢肯定有人知道这种行为。我试过谷歌搜索,但一切似乎都引用了明确的交易。
  • 他们确实有不同的行为 XACT_ABORT 在触发器中隐式启用。 RAISERROR 不被 XACT_ABORT 尊重,但 THROW 是。不知道为什么 CATCH 块会有所作为
  • 行为差异的原因是当XACT_ABORTON并且在try块中发生错误并且无法提交(XACT_STATE是@987654336 @)。如果你真的需要这种奇怪的行为,你可以在触发器中SET XACT_ABORT OFF;

标签: sql-server tsql sql-server-2016


【解决方案1】:

如果在一个事务中发生错误,该事务将被回滚。这是指交易概念。当您调用存储过程时,将启动一个事务。然后它会导致您的触发器被触发并引发错误。事务将自动回滚。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-01-21
    • 2018-09-19
    • 1970-01-01
    • 2015-01-20
    • 2017-10-08
    • 2023-04-02
    相关资源
    最近更新 更多