为什么我的更新后触发器在插入时执行,尽管我也有单独的插入触发器

Why my after update trigger is executing on insert although I have separate trigger for insert as well

/* trigger for update */
create trigger add_date
on students 
after update
as
    update students 
    set dtModify = getdate()
    where id = (select id from inserted)

/* trigger for insert */
create trigger add_date_insert 
on students 
after insert
as 
    update students 
    set dtEnter = getdate() 
    where id = (select id from inserted)

如果您对 inserted 感到困惑,则无需担心。此 table 具有触发触发器的插入行。

现在SQL服务器inserteddeleted

中只有两个这样的table
  • 在插入的情况下,inserted 插入了行。
  • 在删除的情况下,deleted 有被删除的行。
  • 在更新的情况下,有问题的行首先被删除,因此放置在 deleted 中,然后插入新行,其中包含您可以在 table inserted 中找到的更新数据.因此,您可能会将更新视为单个操作,但实际上它是删除和插入这两个操作的组合。

如果你想让你的触发器只在更新的情况下 运行 逻辑,你可以像这样进行 IF 检查:

If exists (Select * from inserted) and exists(Select * from deleted)

然后像这样将触发逻辑放在这个块中

If exists (Select * from inserted) and exists(Select * from deleted)
BEGIN
--Update Logic
END
If exists (Select * from inserted) and not exists(Select * from deleted)
BEGIN
--Inser Logic
END

首先 - 对于 INSERT - 我会使用带有 默认约束 DATETIME2(3) 列 - 然后你不需要触发器:

CREATE TABLE dbo.Students
(
    // your columns here
    dtEnter DATETIME2(3)
        CONSTRAINT DF_Students_dtEnter DEFAULT (SYSDATETIME())
)

现在,每次您插入一行并且您指定列列表中的dtEnter列以插入值时 - 它会自动设置来自 SQL 服务器:

INSERT INTO dbo.Students (list-of-columns-WITHOUT-dtEnter)
VALUES (list-of-values)

对于更新,您需要使用触发器 - 不能为此使用默认约束。使用此触发器 - 确保处理 Inserted 可能包含多行的事实!

CREATE TRIGGER add_date
ON dbo.Students 
AFTER UPDATE
AS
    UPDATE dbo.students 
    SET dtModify = SYSDATETIME()
    WHERE id IN (SELECT id FROM inserted)