The following triggers are meant to automate updates when a row is updated in a locations table. Changes can occur one row at a time, or 1-n many rows at a time. However, when updating a single row, while the "locations_geteditdate" is enabled, a new time stamp is written to all 28K rows in the locations table. I know I'm missing something obvious here, thanks for the help.
ALTER TRIGGER [dbo].[locations_geteditdate]
ON [dbo].[TBL_LOCATIONS]
instead of update
AS
begin
declare @recs INT
select @recs = COUNT(*)
from dbo.TBL_LOCATIONS a
join inserted i on i.Location_ID = a.Location_ID
if @recs > 0
update dbo.TBL_LOCATIONS
SET EditDate = GETDATE()
end
GO
alter TRIGGER [dbo].[locations_move_topo]
ON [dbo].[TBL_LOCATIONS]
for update
AS
BEGIN
update dbo.TBL_LOCATIONS
set topo_name = dbo.TLU_TOPO_BOUNDS.name
FROM dbo.TBL_LOCATIONS
inner join dbo.TLU_TOPO_BOUNDS
on dbo.TBL_LOCATIONS.Location_ID = dbo.TBL_LOCATIONS.Location_ID
where (TLU_TOPO_BOUNDS.Shape.STContains(TBL_LOCATIONS.SHAPE) = 1) ;
END
Accepted answer:
alter TRIGGER [dbo].[locations_geteditdate]
ON [dbo].[TBL_LOCATIONS]
for update
as
begin
update dbo.TBL_LOCATIONS
SET EditDate = GETDATE()
from dbo.TBL_LOCATIONS locn
inner join inserted i on i.location_id = locn.Location_ID
end
GO
In your if condition (in locations_geteditdate
) you have no where clause; therefore it is including all records:
if @recs > 0
update dbo.TBL_LOCATIONS
SET EditDate = GETDATE()
WHERE ???
end
You correctly used the inserted
table to see what had been updated but only to identify a record count
So reading the code you've put in the trigger, it looks like what you're trying to do is just apply a timestamp to the table to show that when it has been updated.
You have at least these options for this:
1. If you don't actually need a recognisable datetime in there you can use a timestamp field instead of a datetime and get it automatically updated.
2. If you can control where updates are performed to the table you can just set EditDate
there (i.e. in stored procedures)
However, assuming that you want a recognisable datetime and you can't control where updates to the table are happening which is why you're implementing a trigger rather than just have a proc set EditDate
, you need to go forward with one of the two types of trigger:
A) So if you persist with an "instead of" trigger you need to understand that it replaces the update that would have happened. So its incumbent upon you to then do the work that it was going to. You check column by column what has changed:
e.g.
IF UPDATE (price)
BEGIN
UPDATE t
SET price = i.price
FROM TBL_LOCATIONS t join inserted i
ON i.locn_id = t.locn_id
END
... repeat for each column (you can merge the updates if it makes sense)
B) Alternatively you can change to an "after" trigger, allow the update to happen (so you don't have to code column by column to check what's been updated) BUT YOU MUST then have a check on the EditDate
column and NOT perform an update if its the EditDate
column that has changed. If you don't do this you'll be in an infinite loop - your proc calls the trigger which calls the trigger etc
i.e. something like:
IF NOT UPDATE(EditDate)
BEGIN
UPDATE dbo.TBL_LOCATIONS
SET EditDate = GETDATE()
FROM dbo.TBL_LOCATIONS locn
INNER JOIN inserted i on i.locn_id = locn.locn_id
END