Reputation: 604
I use SQL Server 2005 and have the below question:
On a table A
, I have a trigger which tracks any insert/update/delete to it. The tracked records are inserted in an audit table (aAudit
). When I run an update on A
, I am seeing two rows in the audit table for each update, which is not what I expect. Here is the trigger that I have defined:
ALTER TRIGGER [ATrigger] ON [dbo].[A]
FOR INSERT, UPDATE, DELETE
AS
INSERT INTO [dbo].[aAudit]
([BusinessDate], [DataTypeId], [BookId], [Version], [DelFlag], [AuditDate], [ExtStatus])
SELECT [BusinessDate], [DataTypeId], [BookId], [Version], 'N', getDate(), 0
FROM inserted
INSERT INTO [dbo].[aAudit]
([BusinessDate], [DataTypeId], [BookId], [Version], [DelFlag], [AuditDate], [ExtStatus])
SELECT [BusinessDate], [DataTypeId], [BookId], [Version], 'Y', getDate(), 0
FROM deleted
Why is the above trigger resulting in one row with DelFlag = 'Y'
and one row with DelFalg = 'N'
in the audit table?
Thanks for taking a look at my question.
Vikram
Upvotes: 3
Views: 2132
Reputation: 754488
In order to separate the three operations INSERT, UPDATE, DELETE, you need to do additional checks:
ALTER TRIGGER [ATrigger] ON [dbo].[A]
FOR INSERT, UPDATE, DELETE
AS
-- those are true INSERTs - the (ID) as primary key is *not* present in the "Deleted" table
INSERT INTO [dbo].[aAudit]([BusinessDate], [DataTypeId], [BookId], [Version], [DelFlag], [AuditDate], [ExtStatus])
SELECT [BusinessDate], [DataTypeId], [BookId], [Version], 'N', getDate(), 0
FROM inserted
WHERE (id) NOT IN (SELECT DISTINCT (id) FROM DELETED)
-- those are true DELETEs - the (ID) as primary key is *not* present in the "Inserted" table
INSERT INTO [dbo].[aAudit]([BusinessDate], [DataTypeId], [BookId], [Version], [DelFlag], [AuditDate], [ExtStatus])
SELECT [BusinessDate], [DataTypeId], [BookId], [Version], 'Y', getDate(), 0
FROM deleted
WHERE (id) NOT IN (SELECT DISTINCT (id) FROM INSERTED)
-- those are the UPDATEs - the (ID) as primary key is present in both the "Inserted" and "Deleted" table
INSERT INTO [dbo].[aAudit]([BusinessDate], [DataTypeId], [BookId], [Version], [DelFlag], [AuditDate], [ExtStatus])
SELECT [BusinessDate], [DataTypeId], [BookId], [Version], 'N', getDate(), 0
FROM Inserted i
INNER JOIN Deleted d on i.ID = d.ID
Upvotes: 4
Reputation: 48016
Behind the scenes, an UPDATE is treated as DELETE the old row and INSERT a new row. So when you do an update, both the INSERTED and DELETED recordsets contain data.
That's why two rows are coming into your audit table from an UPDATE statement.
Upvotes: 6