在配置触发器时更新表中的列时出现错误

Posted

技术标签:

【中文标题】在配置触发器时更新表中的列时出现错误【英文标题】:I am getting error while updating a column in a table on while trigger configured 【发布时间】:2021-11-13 12:32:58 【问题描述】:

我收到此错误:

消息 217,级别 16,状态 1,过程 trg_upd,第 7 行 [批处理开始第 0 行] 超出最大存储过程、函数、触发器或视图嵌套级别(限制为 32)。

当我在我的数据库中使用此触发器时:

CREATE TRIGGER trg_upd_inrt
ON [dbo].[tbl_A]
AFTER UPDATE
AS
BEGIN
    SET NOCOUNT ON;

    UPDATE A
    SET [Desc] = CASE i.[Desc]
                     WHEN 'HR DD' THEN 'HRDD'
                     WHEN 'H PP' THEN 'HPP'
                     WHEN 'RPT AR' THEN 'RPTARIN'
                     WHEN 'APPP PPLE' THEN 'APPLE'
                     WHEN 'HR DD' THEN 'HRDD'
                     ELSE Desc
                 END 
    FROM tbl_A a
    INNER JOIN deleted i ON a.id = i.id 
END

【问题讨论】:

所以想想你的触发器是做什么的。您有一个更新表的语句。这将导致您的触发器触发 - 这会更新同一个表。然后导致相同的触发器触发更新同一个表。等等。有一个选项可以禁用此 [触发递归](docs.microsoft.com/en-us/sql/database-engine/configure-windows/… 或者您可以更正逻辑以避免递归。顺便说一句,当 Desc 不包含 5 个值之一时会发生什么?彻底测试。 @SMor ELSE 描述。我不想禁用触发器。我更新代码 您没有阅读链接。禁用触发递归。但是你犯了一个常见的错误。您永远不应该更新不需要更新的行。触发器应该检查以确定它执行的操作是否确实需要执行。当触发器执行时,您会惊讶地发现插入的表可以包含零行。 如果您使用来自another answer 的代码,您真的应该在问题中引用它。 【参考方案1】:

不幸的是,SQL Server 并没有让你做你想做的事情变得非常简单。您需要使用 instead of 触发器并更新 all 列:

CREATE TRIGGER trg_upd_inrt ON [dbo].[tbl_A] INSTEAD OF UPDATE
AS BEGIN
    SET NOCOUNT ON;

    UPDATE A
        SET [Desc] = CASE i.[Desc]
                         WHEN 'HR DD' THEN 'HRDD'
                         WHEN 'H PP' THEN 'HPP'
                         WHEN 'RPT AR' THEN 'RPTARIN'
                         WHEN 'APPP PPLE' THEN 'APPLE'
                         WHEN 'HR DD' THEN 'HRDD'
                         ELSE i.[Desc]
                     END,
            COL1 = i.Col1,
            COL2 = i.Col2,
            . . . -- all the rest of the columns that might be updated
        FROM tbl_A a INNER JOIN
             inserted i
             ON a.id = i.id ;

END;

请注意,这使用 new 值而不是 old 值进行替换。这对我来说很有意义。由于表别名,我假设您确实打算使用inserted 而不是deleted

如果您确实需要这两个值,只需将两者都包含在 FROM 子句中:

    FROM tbl_A a INNER JOIN
         inserted i
         ON a.id = i.id INNER JOIN
         deleted d
         ON d.id = d.id

【讨论】:

以上是关于在配置触发器时更新表中的列时出现错误的主要内容,如果未能解决你的问题,请参考以下文章

在更新触发之前执行时出现约束冲突错误

MySql 触发器删除同一张表中的子记录

插入后使用 SQL Server 触发器更新另一个表中的列

编译触发器时出现 Oracle 错误 ORA-00922

如何在更新单独表中的列的视图上创建触发器?

Oracle - 在没有触发器的情况下更新表时出现“表正在变异,触发器/函数可能看不到它”错误