这是一个非常有趣的问题。我正在使用SQL Server 2008。
我在一个公用表上有两个触发器,例如“CommonTable”。一个触发器在更新上,另一个在插入/更新/删除上。

  • 在第一个触发器“Trigger1”中,我会进行检查/回滚,有时会根据业务逻辑更改新的插入值。
    这是示例代码

  • --
    CREATE TRIGGER [dbo].[Trigger1] ON [dbo].[CommonTable]
    FOR UPDATE
    UPDATE [CommonTable]
    SET
        [StatusCode] = 'New Value'
    WHERE
    [RecId] = 'rec id value'
    
  • 在第二个触发器“Trigger2”中,我将来自“CommonTable”表的新插入/删除/更新值存储到另一个表“CommonTable_History”中,以进行历史记录跟踪。
    这是示例代码

  • --
    CREATE TRIGGER [dbo].[Trigger2] ON [dbo].[CommonTable]
    FOR INSERT, UPDATE, DELETE
    
    --based on logic read the value from DELETED or INSERTED table and store in other table.
    
    SELECT @RowData = (SELECT * FROM DELETED AS [CommonTable] WHERE [RecId] = @RowRecId FOR XML AUTO,                       BINARY BASE64 , ELEMENTS)
    
    --and then insert @RowData in 'CommonTable_History' table.
    

    在“sp_settriggerorder”的帮助下,我设置了这些触发器的执行顺序,因此首先执行“Trigger1”,然后执行“Trigger2”。

    第二个触发器“Trigger2”适用于插入/删除值。如果首次触发“Trigger1”未更改新的插入值,则对新的插入值工作正常。

    但是在某些情况下,“Trigger1”中的插入值已更改。假设[StatusCode] ='新值',而旧值是'旧值',则“触发器2”仍存储“旧值”而不是“新值”。
    为什么因为“Trigger1”更改了值,但该值仍未存储在数据库中,并且在插入之前执行“Trigger2”之前,为什么?
    现在我的要求是,在这里我要存储“新值”。

    所以我想,让“Trigger2”使用“AFTER”关键字。但是“FOR”和“AFTER”的行为相同无法解决问题。

    然后我想,让“Trigger2”使用“INSTEAD OF”关键字。但是“INSTEAD OF”给出了以下错误
    “无法创建INSTEAD OF DELETE或INSTEAD OF UPDATE触发器。这是因为表具有带有级联DELETE或UPDATE的FOREIGN KEY。”

    我无法使用表'CommonTable'的级联DELETE或UPDATE来删除FOREIGN KEY。

    如果您还有其他替代解决方案,请告诉我。
    -维克拉姆·格洛特(Vikram Gehlot)

    最佳答案

    我认为您的第二个触发器需要使用实际表中的值,而不是插入/删除表中的值来填充日志表-插入/删除将始终具有未更改的原始值,而更改后的值将显示在表中。将第二个触发器设为“After”触发器,因此您不必使用sp_settriggerorder。像这样,例如:

    SET ANSI_NULLS ON
    GO
    SET QUOTED_IDENTIFIER ON
    GO
    CREATE TRIGGER [dbo].[trg_Trig1]
       ON  [dbo].[TestTable]
       FOR INSERT
    AS
    BEGIN
        -- SET NOCOUNT ON added to prevent extra result sets from
        -- interfering with SELECT statements.
        SET NOCOUNT ON;
    
        update TestTable
        set [value] = 10
        where [value] = 25
    
    END
    
    SET ANSI_NULLS ON
    GO
    SET QUOTED_IDENTIFIER ON
    GO
    CREATE TRIGGER [dbo].[trg_Trig2]
       ON  [dbo].[TestTable]
       AFTER INSERT
    AS
    BEGIN
        -- SET NOCOUNT ON added to prevent extra result sets from
        -- interfering with SELECT statements.
        SET NOCOUNT ON;
    
        -- Insert statements for trigger here
        insert into log_TestTable
        (id, description, [value])
        select tt.id, tt.description, tt.[value]
        from inserted i
            LEFT JOIN TestTable tt
                ON tt.id = i.id
    
    END
    

    10-04 14:40
    查看更多