SQL Server 触发器 - 一个失败一个没有

Posted

技术标签:

【中文标题】SQL Server 触发器 - 一个失败一个没有【英文标题】:SQL Server triggers - one fails one doesn't 【发布时间】:2011-08-17 15:27:38 【问题描述】:

我们有一个为一组大约 40 个表动态生成的触发器。考虑到触发器在表A 上的情况,它以两种方式修改表B

    在表B 中的现有行上设置脏标志 在表B 中插入任何缺失的行

两个表之间有一个链接,这样A.bIDB.id 的外键。

本周我们发现,在至少一个表上,触发器未能执行第 2 步(我们不确定它是否执行第 1 步)。但它似乎适用于大多数其他表。


一时兴起,我们的一位开发人员将触发器更改为“更高效”。但后来问题似乎消失了......

我们不太清楚这两个触发器之间有什么不同,有什么见解吗?

损坏的触发器:

CREATE TRIGGER [A_Dirty] ON [A] AFTER INSERT, UPDATE, DELETE
BEGIN
    SET NOCOUNT ON;

    UPDATE [B] SET [timeDirty] = GETUTCDATE() WHERE [id] IN (SELECT [bID] FROM inserted);
    UPDATE [B] SET [timeDirty] = GETUTCDATE() WHERE [id] IN (SELECT [bID] FROM deleted);

    INSERT INTO [B] ([id], [timeDirty])
        SELECT DISTINCT [bID], GETUTCDATE() FROM inserted
        WHERE [bID] NOT IN (SELECT [id] FROM [B])
END

工作触发器:

CREATE TRIGGER [A_Dirty] ON [A] AFTER INSERT, UPDATE, DELETE
BEGIN
    SET NOCOUNT ON;

    UPDATE [B] SET [timeDirty] = GETUTCDATE() FROM inserted WHERE [id] = [bID];
    UPDATE [B] SET [timeDirty] = GETUTCDATE() FROM deleted WHERE [id] = [bID];

    INSERT INTO [B] ([id], [timeDirty])
        SELECT DISTINCT [bID], GETUTCDATE()
            FROM inserted
        LEFT OUTER JOIN [B]
            ON [B].[id] = inserted.[bID]
        WHERE [B].[id] IS NULL
END

【问题讨论】:

第一个查询使用 [B].id,第二个 - [B].guid 用于加入。是不是印错了? 抱歉,这是一个印刷错误。我已经在问题中更正了。 【参考方案1】:

[B] 中的 [id] 是否有 NULL 值?如果是这样,NOT IN 将无法正常工作。您需要更新到以下内容:

INSERT INTO [B] ([id], [timeDirty])
    SELECT DISTINCT [bID], GETUTCDATE() FROM inserted
    WHERE [bID] NOT IN (SELECT [id] FROM [B] WHERE [id] IS NOT NULL)

【讨论】:

[id] 字段不可为 NULL,因此不存在 NULL 值。

以上是关于SQL Server 触发器 - 一个失败一个没有的主要内容,如果未能解决你的问题,请参考以下文章

SQL Server INSTEAD OF INSERT 触发器失败

SQL Server 禁用所有触发器 - 找不到对象“XXXX”,因为它不存在或您没有权限

SQL Server 在触发器中引发错误“触发器中的事务注定要失败。批处理已中止。”

SQL Server基础之登陆触发器

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

SQL Server 触发器认为表中没有重复项