i have what seems like a basic scenario for a db trigger in SQL server and i am running into an issue.
i have table Users (id, name, phone, etc) and i have tables UsersHistory (id, user_id action, fields, timestamp)
i want a database trigger where anytime inserts, updates or deletes into Users, i want a new record created in UsersHistory with the user id and the action that was done (insert new, updated fields, deleted id. Basically an audit log table.
this is how far i got, but i can’t figure out how to:
- Get the id on modify and deletes and also
- How to get a list of fields that have changed and the action that was committed (insert, delete, update)
CREATE TRIGGER Update_Users_History
ON Users
AFTER INSERT,DELETE,UPDATE
AS
BEGIN
-- Insert statements for trigger here
insert into UsersHistory (user_id, [action], [fields], timestamp)
select max(id) as user_id, {action ??},{fields??} getdate() from Users)
END
GO
any suggestions?
The easiest might be to just simply create three triggers – one for each operation:
That way, things are simple and you easily understand what you’re doing, plus it gives you the ability to turn off a trigger for a single operation, if you e.g. need to insert or delete a huge list of items.
Inside the trigger, you have two “pseudo-tables” –
Inserted(for INSERT and UPDATE) andDeleted(for UPDATE and DELETE). These pseudo tables contain the values for the newly inserted values (or the updated ones in UPDATE), or the ones that were deleted (for DELETE) or have been updated (the old values, before the update, for the UPDATE operation).You need to be aware that a trigger will be called once even if you update a huge number of rows, e.g.
InsertedandDeletedwill typically contain multiple rows.As a sample, you could write a “AFTER INSERT” trigger like this (just guessing what your table structure might be….):
You are looking for a way to find out which “action” this trigger caused? I don’t see any way to do this – another reason to keep the three trigger separate. The only way to find this out would be to count the rows in the
InsertedandUpdatedtables:UPDATEInsertedtable has rows, but theDeleteddoes not, it’s anINSERTInsertedtable has no rows, but theDeleteddoes, it’s aDELETEYou’re also looking for a “list of fields that were updated” – again, you won’t have any simple solution, really. You could either just loop through the fields in the “Users” table that are of interest, and check
but that gets a bit tedious.
Or you could use the
COLUMNS_UPDATED()function – this however doesn’t give you a nice list of column names, but a VARBINARY in which each column is basically one bit, and if it’s turned on, that column was updated. Not very easy to use…..If you really want to create a single, big trigger, this could serve as a basis – it detects what operation has caused the trigger to fire, and will insert entries into your User_History table:
I haven’t included the figuring out which fields have been updated part just yet – that’s left as an exercise to the reader 🙂
Does that help at all?