我有2个数据触发器,一个应该在更新之后触发,另一个在插入之后触发。这是更新触发器的开头如下所示:
USE [Database]
GO
SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO
ALTER TRIGGER [dbo].[UpdateTrigger]
ON [dbo].[Table1]
AFTER UPDATE
AS
BEGIN
(...)
后插入触发器看起来完全相同,除了事先有AFTER INSERT而不是AFTER UPDATE。当我更新Table1时,只触发更新触发器。但是,当我插入时,两个触发器都被触发。为什么?我该如何解决?
答案 0 :(得分:0)
当触发器触发时,有2个虚拟表:DELETED和INSERTED。当您插入记录时,只有INSERTED表中的记录,但是当您更新记录时,您在DELETED表中有旧记录,在INSERTED表中有新记录。所以,基本上当你做UPDATE时,你正在做DELETE和INSERT。您可以通过识别DELETED表中是否有记录来轻松解决这个问题。如果有,那么它是UPDATE,如果没有那么它就是INSERT。
答案 1 :(得分:0)
我和JerryBox有相同的经验,当插入触发器触发时,单独的更新触发器将触发。
我想要的是在插入新记录时,插入触发器将在创建记录时插入日期时间戳,并插入创建记录的用户名。相反,如果记录已更新,则添加/更新上次修改的日期时间并最后通过用户名修改。
在我的情况下,当将新记录插入表中时,插入触发器将触发并向SAME表中的字段添加值(即 CreatedBy 和 CreatedDateTime 字段)。这些触发器是通过更新触发器“看到”的,作为对现有记录的更新,因此还将插入 ModifiedBy 和 ModifiedDateTime 字段。
换句话说,插入新记录将同时触发插入和更新触发器。
在阅读Dmitrij Kultasev发表的评论时,我想到了以下解决方案:
将两个触发器组合为一个触发器会导致AFTER INSERT触发器更新记录不会触发AFTER UPDATE触发器。
USE [Database]
GO
CREATE TABLE [dbo].[Table1](
[id] [int] IDENTITY(1,1) PRIMARY KEY,
[Data] [nvarchar](255) NULL,
[CreatedBy] [nvarchar](255) NULL,
[CreatedDateTime] [datetime] NULL,
[ModifiedBy] [nvarchar](255) NULL,
[ModifiedDateTime] [datetime] NULL)
GO
CREATE TRIGGER [dbo].[UpdateTrigger]
ON [dbo].[Table1]
AFTER INSERT, UPDATE
AS
BEGIN
IF EXISTS (SELECT 1 FROM deleted)
UPDATE [dbo].[Table1]
SET [ModifiedBy] = SYSTEM_USER,
[ModifiedDateTime] = SYSDATETIME()
FROM inserted i
WHERE i.id = [dbo].[Table1].id
ELSE
UPDATE [dbo].[Table1]
SET [CreatedBy] = SYSTEM_USER,
[CreatedDateTime] = SYSDATETIME()
FROM inserted i
WHERE i.id = [dbo].[Table1].id
END
GO
编辑:格式化,改进了解释以响应来自andronicus的反馈