Sql server 更新时不会为所有行触发触发器(随机)

Sql server 更新时不会为所有行触发触发器(随机),sql-server,tsql,database-trigger,Sql Server,Tsql,Database Trigger,我创建了一个触发器来捕获副本表中的所有插入、更新和删除操作,但在更新的情况下,插入了两行,一行具有更新前的值,另一行具有更新后的值,但它没有按预期工作 我已经尝试了所有可能的方法来做这件事。现在,我想知道是应该在触发器级别使用事务进行更新操作,还是应该尝试其他操作 ALTER TRIGGER [dbo].[trgAfterInsertUpdateDelete_xyz] ON [dbo].[xyz] FOR UPDATE,INSERT, DELETE AS declare @accountID

我创建了一个触发器来捕获副本表中的所有插入、更新和删除操作,但在更新的情况下,插入了两行,一行具有更新前的值,另一行具有更新后的值,但它没有按预期工作

我已经尝试了所有可能的方法来做这件事。现在,我想知道是应该在触发器级别使用事务进行更新操作,还是应该尝试其他操作

ALTER TRIGGER [dbo].[trgAfterInsertUpdateDelete_xyz] ON [dbo].[xyz] 
FOR UPDATE,INSERT, DELETE
AS
declare @accountID int;
declare @billingDate date;
declare @amount decimal(18, 2);

---- Get data from inserted/ updated
select @accountID = i.AccountID from inserted i;    
select @billingDate=i.BillingDate from inserted i;  
select @amount=i.Amount from inserted i;

-- Insert Case
IF EXISTS( SELECT * FROM inserted) AND NOT EXISTS(SELECT * FROM deleted) 
BEGIN
    insert into xyz_Audit
    (AccountID, BillingDate, Amount, Audit_Action) 
    values(@accountID,@billingDate,@amount,'INSERT');
END

-- Update Case
IF EXISTS( SELECT * FROM inserted) AND EXISTS(SELECT * FROM deleted)
BEGIN
    INSERT INTO xyz_Audit
    (AccountID, BillingDate, Amount, Audit_Action)
    SELECT d.AccountID, d.BillingDate, d.Amount,             
            'BeforeUpdate'  FROM Inserted i
    INNER JOIN Deleted d ON i.ID = d.ID

    INSERT INTO xyz_Audit
    (AccountID, BillingDate, Amount,Audit_Action) 

         values(@accountID,@billingDate,@amount,'AfterUpdate');
END


-- Delete Case
IF EXISTS( SELECT * FROM deleted) AND NOT EXISTS(SELECT * FROM inserted)
BEGIN
    INSERT INTO xyz_Audit
    (AccountID, BillingDate, Amount, Audit_Action) 
    select accountID,billingDate,amount, 'DELETE'
    from deleted
END


我希望如果更新了9条记录,那么所有行都应该有更新前后的值,但有时会跳过。如您所见,对于Inst.8,应该有前后两行,但它只捕获了前一行,然后插入,但实际上并没有删除和插入行,只进行了更新。有时在9行中,它只在更新行之前而不是更新行之后拾取,有时在更新行之后而不是更新行之前拾取2或3行。

您的触发器假定插入/更新/删除操作只影响一行。这意味着插入的
或删除的
可能包含多行

下面的部分不处理这个问题

---- Get data from inserted/ updated
select @accountID = i.AccountID from inserted i;    
select @billingDate=i.BillingDate from inserted i;  
select @amount=i.Amount from inserted i;
事实上,你根本不需要以上这些。您应该直接从
插入的
删除的
表中插入
审计

例如,
“插入案例”
应该是

-- Insert Case
IF EXISTS( SELECT * FROM inserted) AND NOT EXISTS(SELECT * FROM deleted) 
BEGIN
    insert into xyz_Audit (AccountID, BillingDate, Amount, Audit_Action) 
    select AccountID, BillingDate, Amount, Audit_Action= 'INSERT'
    from   inserted;
END

同样,您需要对更新部分进行相应的更改。假设插入/更新/删除操作只影响一行,那么对于删除部分,您已经正确地执行了该操作。这意味着插入的
或删除的
可能包含多行

下面的部分不处理这个问题

---- Get data from inserted/ updated
select @accountID = i.AccountID from inserted i;    
select @billingDate=i.BillingDate from inserted i;  
select @amount=i.Amount from inserted i;
事实上,你根本不需要以上这些。您应该直接从
插入的
删除的
表中插入
审计

例如,
“插入案例”
应该是

-- Insert Case
IF EXISTS( SELECT * FROM inserted) AND NOT EXISTS(SELECT * FROM deleted) 
BEGIN
    insert into xyz_Audit (AccountID, BillingDate, Amount, Audit_Action) 
    select AccountID, BillingDate, Amount, Audit_Action= 'INSERT'
    from   inserted;
END

同样,您需要对更新部分进行相应的更改。您已经正确地完成了删除部分的操作

ok谢谢您的回复。你100%确信这是唯一的问题。现在,无论何时更新9行或18行,它都会捕获所有行的前后行。因为有时它以适当的方式工作,有时又不是一件事,触发器的第二次更新部分是否需要事务?它是按顺序插入数据还是随机插入数据?表示指令1同时具有前后行或以某种随机方式,它将按照您的insert语句的顺序。谢谢@squirrel在尝试一段时间后,如果数据捕获中没有出现错误,它肯定会接受作为答案。非常感谢uOkk的回复。你100%确信这是唯一的问题。现在,无论何时更新9行或18行,它都会捕获所有行的前后行。因为有时它以适当的方式工作,有时又不是一件事,触发器的第二次更新部分是否需要事务?它是按顺序插入数据还是随机插入数据?表示指令1同时具有前后行或以某种随机方式,它将按照您的insert语句的顺序。谢谢@squirrel在尝试一段时间后,如果数据捕获中没有出现错误,它肯定会接受作为答案。非常感谢你