How to use update trigger to update another table? - sql

I am new to triggers and want to create a trigger on an update of a column and update another table with that value.
I have table1 with a year column and if the application updates that year column I need to update table 2 with the year the same year.
ALTER TRIGGER [dbo].[trig_UpdateAnnualYear]
ON [dbo].[table1]
AFTER UPDATE
AS
if (UPDATE (intAnnualYear))
BEGIN
-- SET NOCOUNT ON added to prevent extra result sets from
-- interfering with SELECT statements.
SET NOCOUNT ON;
-- Insert statements for trigger here
Update table2 set AnnualYear = intAnnualYear where table2.ID = table1.ID
END

You don't reference table1 inside the trigger. Use the inserted pseudo table to get the "after" values. Also remember that an update can affect multiple rows.
So replace your current update statement with
UPDATE table2
SET table2.annualyear = inserted.intannualyear
FROM table2
JOIN inserted
ON table2.id = inserted.id

You only need to update the records in table2 if the column intannualyear is involved. Also, this is an alternative UPDATE syntax across two tables from what Martin has shown
IF UPDATE(intannualyear)
UPDATE table2
SET annualyear = inserted.intannualyear
FROM inserted
WHERE table2.id = inserted.id

According to this question, if there's only one "downstream" table then another option with a properly defined foreign key relation would be Cascaded update.

To supplement the above answers, if you have to check more than one column you can use a INNER JOIN between inserted and deleted, or several UPDATE() calls:
IF ( UPDATE(Col1) OR UPDATE(Col2) ) BEGIN ...

Related

Database After Update Trigger From Inserted But Not Inserted? [SQL Server]

I'm trying to create a SQL Server trigger that when an update on table 1 happens in the val2 column, it takes that value and updates table2. I'm struggling to understand how to do this properly on something that sounds easy.
Image of tables
I believe my issue is trying to set a value that is not actually from inserted. (The only value getting updated is val2). I don't know how I can pair where to do the update other than grabbing the ID also on the updated row to compare to the place I want to update. Any help/advice on this would be greatly appreciated. Below is my current trigger that does not work.
CREATE TRIGGER Pull_ID on table1
AFTER UPDATE
AS
BEGIN
#id_ = id from inserted
#val2_ = val2 from inserted
UPDATE table2
SET val2 = #val2_
FROM
WHERE table2.id = #id_
END
You need to build your trigger so that it can handle multiple rows - always.
So you a proper set-based approach, not relying on the false assumption that you only get one row.
Try this:
CREATE TRIGGER Pull_ID on table1
AFTER UPDATE
AS
UPDATE table2
SET val2 = i.val2
FROM Inserted i
WHERE table2.id = i.id
The Inserted pseudo table contains all the rows that have been updated - their new values after the UPDATE. Join that table with your Table2 based on the primary key column (assuming that's the Id) and use a proper, set-based, multi-row capable single UPDATE statement - and you're done!

SQL Trigger to update multiple columns in a View

I have this trigger that updates the value format of a column, But I would like to make it update on more then one column in a view instead of a table.
The trigger;
CREATE TRIGGER [dbo].[TriigerName]
ON [dbo].[Table]
AFTER INSERT
AS
BEGIN
UPDATE
t
SET
t.ColName = dbo.FunctionName(i.ColName)
FROM
dbo.table t
INNER JOIN
inserted i
ON
i.PrimaryId = t.PrimaryId
END
I have tried adding a second t.colName = dbo.FunctionName(i.colName) under SET but that did not work. The query ran, but did not update the value in the second column.
How can I modify this trigger to make it run on a view?
Thanks
EDIT 1:
I get this error ; View or function 't' is not updatable because the modification affects multiple base tables.
and I also changed AFTER INSERT to INSTEAD OF INSERT.
I think that your error message is normal. I guess your view is based on multiple tables
Any INSERT, UPDATE, or DELETE operation on a join view can modify only one underlying base table at a time.
Check this link:
http://docs.oracle.com/cd/B10501_01/server.920/a96521/views.htm#391
As user3238101 said, you cannot update 2 different tables with one statement, so you need to make 2 statements.
CREATE TRIGGER [dbo].[TriigerName]
ON [dbo].[Table]
AFTER INSERT
AS
BEGIN
UPDATE
t
SET
t.ColName = dbo.FunctionName(i.ColName)
FROM
dbo.table t
INNER JOIN
inserted i
ON
i.PrimaryId = t.PrimaryId
UPDATE
t
SET
t.ColName2 = dbo.FunctionName2(i.ColName2)
FROM
dbo.table t
INNER JOIN
inserted i
ON
i.PrimaryId = t.PrimaryId
END

After insert trigger for updating a column

I am writing an after insert trigger trying to find a solution to this problem here:
https://stackoverflow.com/questions/19355644/dead-ends-all-around-trying-to-update-geography-column
What I am unsure of is how to write the trigger to take into consideration multiple records as explained here as a potential you need to code for.
So far I had this but it applies only to a single record so if the table had 100 records inserted in a batch 99 would not be updated. This is my understanding so far and may not be correct.
create trigger tri_inserts on [dbo].[Address]
after insert
as
set nocount on
update Address
SET AddyGeoCode = GEOGRAPHY::Point(inserted.AddyLat, inserted.Addylong, 4326)
GO
Would I say join to the inserted table to discover / update all the new records?
In case it is needed my Address table schema is AddyLat & AddyLong decimal(7,4) and AddyGeoCode Geography.
TIA
Yes, you need to join on inserted table.
UPDATE a
SET a.AddyGeoCode = GEOGRAPHY::Point(a.AddyLat, a.Addylong, 4326) --you can use AddyLat&Long from either a or i
FROM Address a
INNER JOIN inserted i ON a.id = i.id --whatever are your PK columns

Merge SQL INSERT with Reference Table

I need to synchronize two tables.
TableA
Id Name
TableB
Id Name RefID --It's a Foreign key, defined as primary key in Table "TableReference"
TableReference
RefID -- Identity Column, auto increment
I need to merge TableA and TableB in such a way that on each insert in TableB, a value should be inserted into TableReference and that inserted value should be copied into RefId column of TableB.
What I am doing?
I am using SSIS hence I need to have a SSIS based solution OR SQL based solution. I know how to merge tables using Merge SQL command but I am not able to insert a value into TableRef and copy it back to TableB. Could not figure out how i can accomplish this. SQL user-defined functions don't allow INSERT so I can't use it.
Merge TabaleB T
Using Table A S
On S.Id=T.Id
WHEN MATCHED THEN
UPDATE
T.ID=S.ID,
T.NAME=S.NAME
WHEN NOT MATCHED BY TARGET THEN
INSERT(S.ID,S.NAME, {Somehow here i need a function call that inserts in TableRef and Returns SCOPE_IDENTITY})
The problem is T-SQL functions don't allow INSERT and a stored procedure can't be called here as Merge doesn't allow any TSQL thing other than INSERT after WHEN NOT MATCHED BY TARGET THEN.
Are you able to add a TRIGGER on your TableB. If so, one option would be to use the INSERTED row and go from there.
Maybe something like this (untested):
CREATE TRIGGER dbo.tr_TableB
ON dbo.TableB
FOR INSERT
AS
BEGIN
SET NOCOUNT ON;
INSERT TableReference DEFAULT VALUES;
DECLARE #RefId INT;
SELECT #RefId = SCOPE_IDENTITY();
UPDATE t1
SET t1.RefId = #RefId
FROM dbo.TableB AS t1
INNER JOIN INSERTED AS i
ON i.Id= t1.Id
END
GO
Good luck.

Identity of inserted/updated row in trigger

I have the following trigger but need ti find the identity of the row so I don't update all records in the table. How can I get the identity of the affected row?
BEGIN
UPDATE tb_Division SET LastModified = GetDate() WHERE "id of inserted/updated row"
END
Since a trigger in MS SQL Server does not distinguish between single-record and multi-record operations, you should JOIN the table with the INSERTED pseudo table or use a subselect:
UPDATE tb_Division
SET LastModified = GETDATE()
WHERE id IN (SELECT id FROM INSERTED)
id being the primary key column of your table.
Have you looked at the id of the inserted logical table? You have to be careful when using triggers, as a trigger may be operating on more than one row:
UPDATE tb_Division AS td
SET LastModified = GetDate()
FROM INSERTED AS i
WHERE td.id = = i.id
See here for more details, and from MSDN:
DML triggers use the deleted and inserted logical (conceptual) tables. They are structurally similar to the table on which the trigger is defined, that is, the table on which the user action is tried. The deleted and inserted tables hold the old values or new values of the rows that may be changed by the user action. For example, to retrieve all values in the deleted table, use:
Mind you - a trigger can deal with a ton of rows at once - you'll have to take that into account!
You need to join your table to be updated with the Inserted pseudo-column on that ID field:
UPDATE dbo.tb_Division
SET LastModified = GetDate()
FROM Inserted i
WHERE tb_Division.Id = i.Id
or something like that.