插入和更新后未触发 SQL Server 触发器

Posted

技术标签:

【中文标题】插入和更新后未触发 SQL Server 触发器【英文标题】:SQL Server Trigger not triggered after insert and update 【发布时间】:2013-09-10 08:25:34 【问题描述】:

我想将一列的内容复制到同一张表的另一列中。因此,我创建了这个触发器:

ALTER TRIGGER [dbo].[kennscht_copy_to_prodverpt]
ON [dbo].[Stammdaten]
AFTER INSERT
AS
UPDATE Stammdaten
SET PRODVERPT = (SELECT KENNSCHT FROM INSERTED)
WHERE SNR = (SELECT SNR FROM INSERTED);

但是当我在表上使用 UPDATE 将 KENNSCHT 更新为不同的值时,PRODVERPT 也不会更新。现在,您可能会争辩说这是因为触发器位于AFTER INSERT 而不是AFTER UPDATE,但是当我更改它以使其由UPDATEINSERT 触发时,每当我更新任何行时,我都会收到一条错误消息SQL 服务器

无法更新行,因为它会使行不唯一或更新多行(2 行)[原文如此]

这里发生了什么?要么触发器什么都不做,要么把整个表弄乱了,使它无法更新。

更新:我还尝试了以下触发器:

UPDATE s
SET s.PRODVERPT = i.KENNSCHT
FROM Stammdaten s
INNER JOIN INSERTED i ON i.SNR = s.SNR;

但它具有完全相同的行为。如果我只使用AFTER INSERT,没有任何变化,如果我使用AFTER INSERT, UPDATE,我会收到上面的错误消息。

更新2:表格中没有多行,我已经检查过了,因为我认为它可能与问题有关。

【问题讨论】:

您的触发器已损坏 - 它假定 inserted 仅包含一行。最好切换到FROM/JOIN 更新样式,这样您就可以将JOINinserted 一起使用,但这似乎不是这里的only 问题,因为如果它导致您出现问题,则错误消息将是关于返回多个值的子查询。 我也尝试了 JOIN - 但效果相同。一旦我使用“UPDATE”作为触发器,它就会给我错误消息。 还将SET NOCOUNT ON; 添加到触发器中。 @MartinSmith 解决了它。我现在可以运行 JOIN 触发器。谢谢!您可以将其设置为答案吗? @FlorianPeschka - SET NOCOUNT ON 也包含在 TToni 的答案中。另外,如果有人启用了递归触发器数据库选项,这会给您带来工作的好处! 【参考方案1】:

如果您将此触发器作为AFTER UPDATE 触发器运行,它会递归运行,因为它总是针对同一个表发出另一个 UPDATE 语句,这会导致触发器的另一个执行。

要解决此问题,您需要将更新触发器设置为INSTEAD OF UPDATE 触发器,或者测试KENNSCHT 列是否已被修改。对于后者,您可以像这样使用UPDATE() 函数:

ALTER TRIGGER [dbo].[kennscht_copy_to_prodverpt_after_update]
ON [dbo].[Stammdaten]
AFTER UPDATE
AS
BEGIN
    SET NOCOUNT ON
    IF (UPDATE(KENNSCHT))
    BEGIN
        UPDATE s
            SET s.PRODVERPT = i.KENNSCHT
            FROM Stammdaten s
            INNER JOIN INSERTED i ON i.SNR = s.SNR
    END
END

【讨论】:

默认情况下不启用递归触发器,如果​​这是问题所在,他们将收到超出递归限制的错误。问题中提到的错误是NOCOUNT ON未打开时来自客户端工具的错误。 我一步一步尝试了这个,但是当我在触发器中设置NOCOUNT ON之后,它已经工作了。 @Florian Pescka:我仍然认为使用我的代码是个好主意。它只在需要时发布另一个更新(并非总是像原始代码那样),并且它更加健壮,因为如果启用递归触发器,它仍然可以工作。 @Martin Smith:感谢您的提醒!我会让答案与这条评论一致,它已经被投票了,我会再为它添加一个 +1。 是的,我仍然使用你的建议,我只是想指出实际的错误是 NOCOUNT。

以上是关于插入和更新后未触发 SQL Server 触发器的主要内容,如果未能解决你的问题,请参考以下文章

如何在 SQL Server 2008 上创建插入更新触发器

sql server 数据库里设置了当插入数据时,便触发器插入更新时间,但我导入数据时,触发器却没有工作。

如何在 SQL Server 触发器中复制插入、更新、删除的行

SQL Server 触发器切换插入、删除、更新

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

SQL Server 触发器插入/更新特定列