Reputation: 630
My knowledge of SQL is pretty limited as I mostly focus in backend Ruby development. However, due to architectural changes and wanting to keep things well designed; I have decided to set up timestamping on the database level rather than on the backend level.
As it goes right now, all of my tables have two columns: CreatedAt
and UpdatedAt
, both with a default value of GETDATE()
.
However, I now need to set up a timestamping trigger for UpdatedAt
, so that every time a row (or rows) are updated, the UpdatedAt
column for those rows gets a brand new timestamp.
I am having trouble with the following trigger I wrote. I am getting an error:
Incorrect Syntax near '='
I am testing out my trigger on my Orders table first, and then I plan to move the functionality to all tables.
CREATE TRIGGER dbo.trgTimestampAfterUpdate
ON Dbo.Orders
AFTER UPDATE
AS
BEGIN
IF EXISTS (SELECT * FROM inserted)
BEGIN
SET UpdatedAt = GETDATE()
END
END
I know that I can access the inserted, and deleted virtual tables when using a trigger. My thought with this query was that I would use inserted in order to distinguish which rows have been updated. If anyone can help that would be great, and also if you wouldn't mind explaining to me what I messed up with my syntax or line of thinking would be greatly appreciated.
Upvotes: 1
Views: 212
Reputation: 24022
You can't really access the inserted tables quite like that. Having just Set UpdatedAt =...
is an incomplete statement. Implicitly it makes sense to you but even in your trigger, you have to make complete SQL statements.
The way to do this is to JOIN to the INSERTED table (in the example below, I'm using a semi-join) You can then use the contents of the INSERTED table to perform another update.
CREATE TRIGGER [dbo].[trgTimestampAfterUpdate] ON dbo.orders
FOR UPDATE
AS
BEGIN
IF NOT(UPDATE(UpdatedAt)) --Avoid triggers firing triggers
BEGIN
UPDATE dbo.orders
SET UpdatedAt = GETDATE()
WHERE id IN ( SELECT id
FROM inserted )
END
END
Two REALLY important things to note in this code example. First Updating the table with the trigger on it will cause the trigger to fire again (creating a loop that will increase until you reach the max level of nested triggers on your system.) I put a check to make sure it terminates if you're only updating the updatedat
column.
Second, never ever assume there is only one row in the inserted table. Something like the code below is a very common mistake
DECLARE @id INT
SELECT @id = id FROM INSERTED
UPDATE MyTable
SET UpdatedAT = GETDATE()
WHERE id = @id
--DON'T DO THIS!
This looks right, and is a common mistake, but it will only ever update 1 record and there could be any number of records in the INSERTED table.
Upvotes: 3