如何在SQL Server触发器中复制插入的,更新的,已删除的行

Def*_*ity 9 t-sql sql-server triggers dml

如果用户更改了表HelloWorlds,那么我想要"他们做的动作",他们做的时间以及原始行插入的副本HelloWorldsHistory.

由于列长度,我宁愿避免单独的插入,更新和删除操作触发器.

我试过这个:

create trigger [HelloWorlds_After_IUD] on [HelloWorlds]
FOR insert, update, delete
as
if @@rowcount = 0 
return
if exists (select 1 from inserted) and not exists (select 1 from deleted)
begin
insert into HelloWorldHistory (hwh_action, ..long column list..)
select 'INSERT', helloWorld.id, helloWorld.text ... and more from inserted
end
else
    if exists (select 1 from inserted) and exists (select 1 from deleted)
    begin
insert into HelloWorldHistory (hwh_action, ..long column list..)
select 'UPDATE', helloWorld.id, helloWorld.text ... and more from deleted 
    end
    else
    begin
insert into HelloWorldHistory (hwh_action, ..long column list..)
select 'DELETE', helloWorld.id, helloWorld.text ... and more from deleted
    end
end
Run Code Online (Sandbox Code Playgroud)

我从未见过插页出现,但我看过更新.我将尝试3个单独的触发器,但保持列列表不会很有趣.

KM.*_*KM. 20

尝试这样的事情:

CREATE TRIGGER YourTrigger ON YourTable
   AFTER INSERT,UPDATE,DELETE
AS

DECLARE @HistoryType    char(1) --"I"=insert, "U"=update, "D"=delete

SET @HistoryType=NULL

IF EXISTS (SELECT * FROM INSERTED)
BEGIN
    IF EXISTS (SELECT * FROM DELETED)
    BEGIN
        --UPDATE
        SET @HistoryType='U'
    END
    ELSE
    BEGIN
        --INSERT
        SET @HistoryType='I'
    END
    --handle insert or update data
    INSERT INTO YourLog
            (ActionType,ActionDate,.....)
        SELECT
            @HistoryType,GETDATE(),.....
            FROM INSERTED

END
ELSE IF EXISTS(SELECT * FROM DELETED)
BEGIN
    --DELETE
    SET @HistoryType='D'

    --handle delete data, insert into both the history and the log tables
    INSERT INTO YourLog
            (ActionType,ActionDate,.....)
        SELECT
            @HistoryType,GETDATE(),.....
            FROM DELETED

END
--ELSE
--BEGIN
--    both INSERTED and DELETED are empty, no rows affected
--END
Run Code Online (Sandbox Code Playgroud)

  • 我强烈建议您从INSERTED表中记录UPDATE.下面是一个示例:插入行数据= AAA(INSERTED = AAA转到日志),将同一行更新为BBB(INSERTED = BBB,DELETED = AAA,我说发送BBB到日志,而不是AAA,已经记录).此外,当使用"IF EXISTS"时,所有"键检查"都不是必需的,只是开销.触发器一次只能触发1个命令,INSERT或UPDATE或DELETE,因此不需要匹配键来确定操作.在触发器中,您永远不会将UPDATE数据与INSERT数据混合在一起. (4认同)
  • @KM由于其简单性和对三种语句的原子性的深入了解而无需PK匹配,因此非常优雅.我甚至使用'MERGE'语句对此进行了测试,该语句似乎将操作混合在一个批次中,但实际上并没有,并且这种逻辑很好. (2认同)

bob*_*obs 6

您需要关联(匹配)插入和删除列中的行.这样的事情应该会更好.

create trigger [HelloWorlds_After_IUD] on [HelloWorlds]
FOR insert, update, delete
as

insert into HeloWorldsHistory
select 'INSERT', helloWorld.id, helloWorld.text ... and more 
from inserted
where myKeyColumn not in (select myKeyColumn from deleted)

insert into HeloWorldsHistory
select 'DELETE', helloWorld.id, helloWorld.text ... and more 
from deleted
where myKeyColumn not in (select myKeyColumn from inserted)

insert into HeloWorldsHistory
select 'UPDATE', helloWorld.id, helloWorld.text ... and more 
from inserted
where myKeyColumn in (select myKeyColumn from deleted)
Run Code Online (Sandbox Code Playgroud)