0
USE [MY_DATABASE_NAME]
GO
/****** Object:  Trigger [dbo].[trg_After_Update]    Script Date: 16.12.2014 23:13:53 ******/
SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO
ALTER TRIGGER [dbo].[trg_After_Update]
ON [dbo].[MY_TABLE_NAME] 
FOR UPDATE
AS
    declare  @FOR_DATE date;
    declare @WRITTEN_ON smalldatetime;
    declare @WRITTEN_BY_WHO NVARCHAR(50); 
    declare @REPORT nvarchar(max);
    declare @HANDLED bit; 
    declare @HANDLED_BY NVARCHAR(50);
    declare @HANDLED_WHEN datetime;
    declare @COMMENT nvarchar(max);
    declare @AUDIT_ACTION NVARCHAR(50);
    declare @AUDIT_TIMESTAMP smalldatetime;


    select @FOR_DATE     = i.FOR_DATE from inserted i;  
    select @WRITTEN_ON = i.WRITTEN_ON from inserted i;
    select @WRITTEN_BY_WHO = i.WRITTEN_BY_WHO from inserted i;
    select @REPORT         = i.REPORT from inserted i;
    select @HANDLED      = i.HANDLED from inserted i;
    select @HANDLED_BY = i.HANDLED_BY from inserted i;
    select @HANDLED_WHEN = i.HANDLED_WHEN from inserted i;
    select @ COMMENT       = i.COMMENT from inserted i;

                   if update(REPORT)
        set @audit_action='Report change';
        if update(COMMENT)
        set @audit_action='Comment change';
        if update(HANDLED)
        set @audit_action='Handled change';

                        insert into AUDIT_MY_TABLE_NAME


(FOR_DATE,WRITTEN_ON,WRITTEN_BY_WHO,REPORT,HANDLED,HANDLED_BY,HANDLED_WHEN,COMMENT,USER,AUDIT_ACTION,AUDIT_TIMESTAMP) 
    values

(@FOR_DATE,@WRITTEN_ON,@WRITTEN_BY_WHO,@REPORT,@HANDLED,@HANDLED_BY,@HANDLED_WHEN,@COMMENT,USER_NAME(USER_ID()),@audit_action,getdate());

此触发器或多或少按预期工作。它记录对 3 个受监控字段的任何更改。但是,将新记录插入此表“MY_TABLE_NAME”会触发上述触发器。然后,当我去查看审计表“AUDIT_MY_TABLE_NAME”时,我看到这条新记录已添加到那里。唯一的区别是“audit_action”字段为空。对审计表的这种插入可能是由另一个触发器在插入后更新“MY_TABLE_NAME”中的 2 个字段引起的。

我的问题是:我有点喜欢这个触发器的工作方式。我想添加的唯一附加功能是“audit_action”读取“新记录”而不是现在显示为空。请注意,我没有记录新记录,但由于这个 After_Update 触发器无论如何都会记录它们,为什么不...... 那么我必须在这个“after_update”触发器中进行什么更改,以便在插入新记录时让“audit_action”在我的审计表中读取“新记录”?

4

1 回答 1

2

当您为单个更新编写触发器时要非常小心,但不要阻止记录批量更新。如果您批量更新 20 条记录,您将在审计表中插入 1 条记录,这将是 20 条记录中的随机一条。

为了满足您的条件而不进行太多更改,您可以像这样修改触发器(这处理批量更新):

ALTER TRIGGER [dbo].[trg_After_Update]
ON [dbo].[MY_TABLE_NAME] 
FOR UPDATE
AS
    INSERT INTO AUDIT_MY_TABLE_NAME (FOR_DATE,WRITTEN_ON,WRITTEN_BY_WHO,REPORT,HANDLED,HANDLED_BY,HANDLED_WHEN,COMMENT,USER,AUDIT_ACTION,AUDIT_TIMESTAMP)
    SELECT i.FOR_DATE, i.WRITTEN_ON, i.WRITTEN_BY_WHO, i.REPORT, i.HANDLED, i.HANDLED_BY, i.HANDLED_WHEN, i.COMMENT, USER_NAME(USER_ID()),
        CASE  -- case statement is in reverse order to match your logic (bottom wins)
            WHEN i.HANDLED <> d.HANDLED THEN 'Handled Changed'
            WHEN i.COMMENT <> d.COMMENT THEN 'Comment Change'
            WHEN i.REPORT <> d.REPORT THEN 'Report Change'
            ELSE 'New Record'
        END,
        GETDATE()
    FROM inserted i
    LEFT JOIN deleted d ON i.pk = d.pk  -- join on your Primary Key that doesn't change
END

但我想知道你认为发生的事情是否正确。当您更新这 3 个字段中的 1 个以上时,所有这些逻辑都将运行。如果您的 3 列中超过 1 列正在更新,则最后一列获胜。我的猜测是,您的“新记录”更新实际上是您UPDATE正在更新的 3 列之外的一个字段。

这是另一种选择,我会让你选择你认为最好的:

ALTER TRIGGER [dbo].[trg_After_Update]
ON [dbo].[MY_TABLE_NAME] 
FOR UPDATE
AS
    INSERT INTO AUDIT_MY_TABLE_NAME (FOR_DATE,WRITTEN_ON,WRITTEN_BY_WHO,REPORT,HANDLED,HANDLED_BY,HANDLED_WHEN,COMMENT,USER,AUDIT_ACTION,AUDIT_TIMESTAMP)
    SELECT i.FOR_DATE, i.WRITTEN_ON, i.WRITTEN_BY_WHO, i.REPORT, i.HANDLED, i.HANDLED_BY, i.HANDLED_WHEN, i.COMMENT, USER_NAME(USER_ID()),
        CASE WHEN i.pk IS NOT NULL AND d.pk IS NULL THEN 'New Record' ELSE
            CASE WHEN i.HANDLED <> d.HANDLED THEN 'Handled Changed. ' ELSE '' END + 
            CASE WHEN i.COMMENT <> d.COMMENT THEN 'Comment Change. ' ELSE '' END + 
            CASE WHEN i.REPORT <> d.REPORT THEN 'Report Change. ' ELSE '' END + 
            CASE WHEN i.HANDLED = d.HANDLED AND i.COMMENT = d.COMMENT AND i.REPORT = d.REPORT THEN 'Other Change.' ELSE '' END
        END,
        GETDATE()
    FROM inserted i
    LEFT JOIN deleted d ON i.pk = d.pk  -- join on your Primary Key that doesn't change
END
于 2014-12-17T03:01:17.660 回答