AFTER UPDATE触发器在INSERT-sql server之后被触发

时间:2017-10-05 12:32:49

标签: sql sql-server datatrigger

我有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时,只触发更新触发器。但是,当我插入时,两个触发器都被触发。为什么?我该如何解决?

2 个答案:

答案 0 :(得分:0)

当触发器触发时,有2个虚拟表:DELETED和INSERTED。当您插入记录时,只有INSERTED表中的记录,但是当您更新记录时,您在DELETED表中有旧记录,在INSERTED表中有新记录。所以,基本上当你做UPDATE时,你正在做DELETE和INSERT。您可以通过识别DELETED表中是否有记录来轻松解决这个问题。如果有,那么它是UPDATE,如果没有那么它就是INSERT。

答案 1 :(得分:0)

我和JerryBox有相同的经验,当插入触发器触发时,单独的更新触发器将触发。

我想要的是在插入新记录时,插入触发器将在创建记录时插入日期时间戳,并插入创建记录的用户名。相反,如果记录已更新,则添加/更新上次修改的日期时间并最后通过用户名修改。

在我的情况下,当将新记录插入表中时,插入触发器将触发并向SAME表中的字段添加值(即 CreatedBy CreatedDateTime 字段)。这些触发器是通过更新触发器“看到”的,作为对现有记录的更新,因此还将插入 ModifiedBy ModifiedDateTime 字段。

换句话说,插入新记录将同时触发插入和更新触发器。

在阅读Dmitrij Kultasev发表的评论时,我想到了以下解决方案:

  1. 将INSERT和UPDATE触发器组合为单个TRIGGER xxx 插入后在xxx上更新,更新...
  2. 检查DELETED表中的旧记录
  3. 如果记录在DELETED表中,则执行更新操作
  4. 如果DELETED表中不存在任何记录,则执行插入操作     执行

将两个触发器组合为一个触发器会导致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的反馈