January 20, 2022 at 3:29 pm
I'm after a simple trigger to audit inserts and deletes on a single table.
If the PK does not exist in the audit table (i.e. an INSERT has occurred) then insert into the audit table.
If the PK exists in the audit table (i.e. an UPDATE has occurred) then insert into the audit table the new values if any of the non-key values have changed.
The table and the audit table will contain the same columns (plus any additional columns required in the audit table).
I'm struggling to find an example.
Also, are the data changes made by a trigger included in the transaction, so that they are rolled back if the INSERT or UPDATE on the table are rolled back - I think that is the case?
January 20, 2022 at 4:33 pm
I did a google search for "Auditing SQL Server with Triggers"
https://www.sqlshack.com/creating-smart-trigger-based-audit-trail-sql-server/
And, searching SQL Server Central for "Audit Triggers", I found
https://www.sqlservercentral.com/scripts/script-generates-audit-triggers
https://www.mssqltips.com/sqlservertip/1468/designing-tables-for-audit-data-in-sql-server/
Michael L John
If you assassinate a DBA, would you pull a trigger?
To properly post on a forum:
http://www.sqlservercentral.com/articles/61537/
January 20, 2022 at 4:48 pm
Thanks. The first one is simple and a good starting point for me.
Why in the below is it necessary to join back to tblOrders?
create trigger tblTriggerAuditRecord on tblOrders
after update, insert
as
begin
insert into tblOrdersAudit
(OrderID, OrderApprovalDateTime, OrderStatus, UpdatedBy, UpdatedOn )
select i.OrderID, i.OrderApprovalDateTime, i.OrderStatus, SUSER_SNAME(), getdate()
from tblOrders t
inner join inserted i on t.OrderID=i.OrderID
end
go
January 20, 2022 at 4:58 pm
It's not. Everything just inserted or updated is in the virtual "inserted" table, so the join adds no value.
Good observation.
January 20, 2022 at 5:01 pm
That join is not needed.
are the data changes made by a trigger included in the transaction, so that they are rolled back if the INSERT or UPDATE on the table are rolled back?
Yes, the trigger is part of the transaction and will be rolled back if the trans fails.
If the PK exists in the audit table (i.e. an UPDATE has occurred) then insert into the audit table the new values if any of the non-key values have changed.
Do you want to log columns only if the value changes? Or just log every column every time?
SQL DBA,SQL Server MVP(07, 08, 09) "It's a dog-eat-dog world, and I'm wearing Milk-Bone underwear." "Norm", on "Cheers". Also from "Cheers", from "Carla": "You need to know 3 things about Tortelli men: Tortelli men draw women like flies; Tortelli men treat women like flies; Tortelli men's brains are in their flies".
January 20, 2022 at 5:22 pm
Good, I couldn't understand why the join was there.
Scott - I would want to log all columns, but only if one or more of the values have changed. An UPDATE that happened to not change any column values would not go into the audit.
January 20, 2022 at 6:10 pm
SET ANSI_NULLS ON;
SET QUOTED_IDENTIFIER ON;
GO
CREATE TRIGGER tblTriggerAuditRecord
ON dbo.tblOrders
AFTER INSERT, UPDATE
AS
SET NOCOUNT ON;
INSERT INTO dbo.tblOrdersAudit
( OrderID, OrderApprovalDateTime, OrderStatus, /*...,*/ UpdatedBy, UpdatedOn )
SELECT i.OrderID, i.OrderApprovalDateTime, i.OrderStatus, /*...,*/ SUSER_SNAME(), GETDATE()
FROM dbo.tblOrders t
INNER JOIN deleted d ON d.OrderID=t.OrderID
WHERE
(d.OrderApprovalDateTime IS NULL OR t.OrderApprovalDateTime <> d.OrderApprovalDateTime) OR
(t.OrderStatus <> d.OrderStatus) /*OR ...*/
/*end of trigger*/
GO
SQL DBA,SQL Server MVP(07, 08, 09) "It's a dog-eat-dog world, and I'm wearing Milk-Bone underwear." "Norm", on "Cheers". Also from "Cheers", from "Carla": "You need to know 3 things about Tortelli men: Tortelli men draw women like flies; Tortelli men treat women like flies; Tortelli men's brains are in their flies".
January 20, 2022 at 6:55 pm
Thanks.
FROM dbo.tblOrders t
INNER JOIN deleted d ON d.OrderID=t.OrderID
I was thinking it was:
FROM dbo.tblOrders t
LEFT JOIN deleted d ON d.OrderID=t.OrderID
or
FROM inserted i
LEFT JOIN deleted d ON i.OrderID=d.OrderID
January 20, 2022 at 8:03 pm
Oops, quite true, since I did a combined trigger.
I suggest separating the INSERT and UPDATE triggers. Then you can use INNER JOIN and not have to test for INSERT vs UPDATE in the trigger.
...
AFTER UPDATE
...
For the INSERT trigger, you don't need to join to anything, since all the columns are known to be "changed", i.e. new.
SQL DBA,SQL Server MVP(07, 08, 09) "It's a dog-eat-dog world, and I'm wearing Milk-Bone underwear." "Norm", on "Cheers". Also from "Cheers", from "Carla": "You need to know 3 things about Tortelli men: Tortelli men draw women like flies; Tortelli men treat women like flies; Tortelli men's brains are in their flies".
Viewing 9 posts - 1 through 8 (of 8 total)
You must be logged in to reply to this topic. Login to reply