SQL Trigger update another table - sql

I am newbie to triggers... can anybody help me with a trigger?
I have Table:
Name | Number
I want to write a trigger when my table receives a query like
update MyTable
set Number = Number + 1
where Name = 'myname'
When this query is running, the trigger should update another table for example:
Update MyTable 2
set Column = 'something'
where Name = 'myname (above name)
Thank you very much !

You will need to write an UPDATE trigger on table 1, to update table 2 accordingly.
Be aware: triggers in SQL Server are not called once per row that gets updated - they're called once per statement, and the internal "pseudo" tables Inserted and Deleted will contain multiple rows, so you need to take that into account when writing your trigger.
In your case, I'd write something like:
-- UPDATE trigger on "dbo.Table1"
CREATE TRIGGER Table1Updated
ON dbo.table1 FOR UPDATE
AS
BEGIN
-- update table2, using the same rows as were updated in table1
UPDATE t2
SET t2.Column = 'something'
FROM dbo.Table2 t2
INNER JOIN Inserted i ON t2.ID = i.ID
END
GO
The trick is to use the Inserted pseudo table (which contains the new values after the UPDATE - it has the exact same structure as your table the trigger is written for - here dbo.Table1) in a set-based fashion - join that to your dbo.Table2 on some column that they have in common (an ID or something).

create a trigger on table 1 for update:
CREATE TRIGGER dbo.update_trigger
ON table1
AFTER UPDATE
AS
BEGIN
DECLARE #Name VARCHAR(50)
SELECT #Name=Name FROM INSERTED
Update MyTable 2
SET Column = 'something'
WHERE Name = #Name
END
GO
try this ;)

Related

Create a trigger that updates a column in a table when a different column in the same table is updated - SQL

How to create a trigger that updates a column in a table when a different column in the same table is updated.
So far I have done the following which works when any new data is created. Its able to copy data from "Purchase Requisition" to "PO_Number" however when data has been modified in "Purchase Requisition" , no changes is made to "PO_Number" and the value becomes NULL. Any kind help will be seriously appreciated.
ALTER TRIGGER [dbo].[PO_Number_Trigger]
ON [dbo].[TheCat2]
AFTER INSERT
AS BEGIN
UPDATE dbo.TheCat2 SET PO_Number=(select Purchase_Requisition from inserted) where DocNo= (Select DocNo from inserted);
END
You need to add 'UPDATE' as well as insert to the trigger, otherwise it will only execute on new data, not updated data. Also added 'top 1' to the select statements from the inserted table to allow this to be 'safe' on batch updates, however it will only update 1 record.
ALTER TRIGGER [dbo].[PO_Number_Trigger]
ON [dbo].[TheCat2]
AFTER INSERT, UPDATE
AS BEGIN
UPDATE dbo.TheCat2 SET PO_Number=(select top 1 Purchase_Requisition from inserted) where DocNo= (Select top 1 DocNo from inserted);
END
This might do what you want:
Your trigger is altering all rows in TheCat2. Presumably, you only want to alter the new ones:
ALTER TRIGGER [dbo].[PO_Number_Trigger]
ON [dbo].[TheCat2] AFTER INSERT
AS
BEGIN
UPDATE tc
SET PO_Number = Purchase_Requisition
FROM dbo.TheCat2 tc JOIN
inserted i
on tc.DocNo = i.DocNo ;
END;
However, perhaps a computed column is sufficient for your purposes:
alter table add PO_Number as Purchase_Requisition;

How to update specific row in datecolumn to date today after update on other column using after update trigger?

How to update date Column DateMod to today's date when Column CustomerProductID is updated (not inserted) using an after update trigger in T-SQL?
Some background info: Table already contains list of products (key column Itemcode), once the CustomerProductID is received it changes the column for that particular row (product) from NULL to integer value. This update is the trigger to update column DateMod to todays date for the row (product).
I am using SSMS 2008 and have something like the following code which changes the whole date column, not the particular date field for the updated row:
CREATE TRIGGER trigger_name
ON Table1
AFTER UPDATE
AS
BEGIN
SET NOCOUNT ON;
IF UPDATE (CustomerProductID) BEGIN
Update Table1
SET DateMod=GETDATE()
END
END
I have read some solutions using old.value and new.value or using where exists (select from inserted/updated), but how does that work? If both methods work, which one is the most beneficial in this case?
Thanks a lot!
I prefer do this as a before update trigger (a logical thing . . . doing updates in after update triggers suggests infinite loops and is not allowed in some databases). But SQL Server doesn't support that.
In any case, the right syntax is to use inserted to join back to the original table:
CREATE TRIGGER trigger_name
ON Table1
AFTER UPDATE
AS
BEGIN
SET NOCOUNT ON;
IF UPDATE(CustomerProductID) BEGIN
Update t1
SET DateMod = GETDATE()
FROM Table1 t1 join
Inserted i
ON Table1.PrimaryKeyColumn = i.PrimaryKeyColumn
END
END
Change the code so PrimaryKeyColumn is the right primary key column.

Creating a trigger to update multiple records after insert sql server 2008

Well basically I need this trigger to work after a user inserts multiple records into the database. So that when an optionID of 0 is inserted and the IsoptionalID = 1, then set the OptionID = NULL
CREATE TRIGGER ThisDatabase
ON OtherTable
AFTER INSERT
AS
BEGIN
DECLARE #OPTIONID INT
SET #OPTIONID = OtherTable.OPTIONID
DECLARE #ISoptional INT
SET #ISoptional = OtherTable.ISoptional
CASE #optionID WHEN 0 and #ISoptional = 1 set update OtherTable set optionid = null end
END
I am not sure about the case itself either.
Thank you in advance
This depends on the key field(s) of the table, but SQL Server triggers always work on the entire data set being modified (Inserted, Updated, or Deleted). So the trigger would something more like:
CREATE TRIGGER ThisDatabase
ON OtherTable
AFTER INSERT
AS
BEGIN
SET NOCOUNT ON
UPDATE ot
SET ot.OptionID = NULL
FROM OtherTable ot
INNER JOIN INSERTED ins
ON ins.KeyField = ot.KeyField
WHERE ins.OptionID = 0
AND ins.IsOptional = 1
END
The INSERTED table has the rows that were either Inserted or Updated (current version).
The DELETED table has the rows that were either Deleted or Updated (old version).
So, the INSERTED and DELETED tables are pre-filtered to only the changed records, but they are not updatable (since the event already happened due to this being an AFTER trigger and SQL Server not having a BEFORE trigger) so you need to do the UPDATE on the real table.
It isn't really clear what you want to do, but here's a skeleton. Just note:
Triggers are created on the table which is being affected (not an Other table)
You can certainly update another table as a consequence of a trigger. This is typically done through a join.
Use the inserted and deleted pseudo-tables to identify the record(s) which have been inserted, updated or deleted.
CREATE TRIGGER TR_TableBeingInsertedInto
ON TableBeingInsertedInto
AFTER INSERT
AS
BEGIN
UPDATE OtherTable
-- What you actually want to do here isn't clear to me
SET OtherTable.OPTIONID =
CASE i.OptionID
WHEN 0 THEN NULL
ELSE OtherTable.OPTIONID
END
FROM OtherTable
-- Inserted has the same schema as TableBeingInsertedInto
INNER JOIN INSERTED i
ON OtherTable.SomeCommonKey = i.SomeCommonKey;
END

Is there a way to make a field only editable by a trigger?

In Sql Server 2008 is there a way to set a field that it can only be changed using a Trigger?
Example:
When you create a record it is set to NULL and then updated by a trigger to e.g 1.
It should not be able to be set to anything other than NULL by the user.
And then when it is updated the trigger will set the value to 2.
create table tmp (a int primary key, b int)
GO
create trigger tr_insupd_tmp on tmp
instead of insert, update
as
if not exists(select * from deleted)
-- Process Insert
insert into tmp
select a, 1
from inserted
else
-- Process Update
update tmp
set b = 2
from tmp t
inner join inserted i on t.a = i.a
GO
Have you considered using using computed columns. If you want data in this column to be only governed by database logic then computed columns are probably way to go.

IF UPDATE() in SQL server trigger

If there's:
IF UPDATE (col1)
...in the SQL server trigger on a table, does it return true only if col1 has been changed or been updated?
I have a regular update query like
UPDATE table-name
SET col1 = 'x',
col2 = 'y'
WHERE id = 999
Now what my concern is if the "col1" was 'x' previously then again we updated it to 'x'
would IF UPDATE ("col1") trigger return True or not?
I am facing this problem as my save query is generic for all columns, but when I add this condition it returns True even if it's not changed...So I am concerned what to do in this case if I want to add condition like that?
It returns true if a column was updated. An update means that the query has SET the value of the column. Whether the previous value was the same as the new value is largely irelevant.
UPDATE table SET col = col
it's an update.
UPDATE table SET col = 99
when the col already had value 99 also it's an update.
Within the trigger, you have access to two internal tables that may help. The 'inserted' table includes the new version of each affected row, The 'deleted' table includes the original version of each row. You can compare the values in these tables to see if your field value was actually changed.
Here's a quick way to scan the rows to see if ANY column changed before deciding to run the contents of a trigger. This can be useful for example when you want to write a history record, but you don't want to do it if nothing really changed.
We use this all the time in ETL importing processes where we may re-import data but if nothing really changed in the source file we don't want to create a new history record.
CREATE TRIGGER [dbo].[TR_my_table_create_history]
ON [dbo].[my_table] FOR UPDATE AS
BEGIN
--
-- Insert the old data row if any column data changed
--
INSERT INTO [my_table_history]
SELECT d.*
FROM deleted d
INNER JOIN inserted i ON i.[id] = d.[id]
--
-- Use INTERSECT to see if anything REALLY changed
--
WHERE NOT EXISTS( SELECT i.* INTERSECT SELECT d.* )
END
Note that this particular trigger assumes that your source table (the one triggering the trigger) and the history table have identical column layouts.
What you do is check for different values in the inserted and deleted tables rather than use updated() (Don't forget to account for nulls). Or you could stop doing unneeded updates.
Trigger:
CREATE TRIGGER boo ON status2 FOR UPDATE AS
IF UPDATE (id)
BEGIN
SELECT 'DETECT';
END;
Usage:
UPDATE status2 SET name = 'K' WHERE name= 'T' --no action
UPDATE status2 SET name = 'T' ,id= 8 WHERE name= 'K' --detect
To shortcut the "No actual update" case, you need also check at the beginning whether your query affected any rows at all:
set nocount on; -- this must be the first statement!
if not exists (select 1 from inserted) and not exists (select 1 from deleted)
return;
SET NOCOUNT ON;
declare #countTemp int
select #countTemp = Count (*) from (
select City,PostCode,Street,CountryId,Address1 from Deleted
union
select City,PostCode,Street,CountryId,Address1 from Inserted
) tempTable
IF ( #countTemp > 1 )
Begin
-- Your Code goes Here
End
-- if any of these "City,PostCode,Street,CountryId,Address1" got updated then trigger
-- will work in " IF ( #countTemp > 1 ) " Code)
This worked for me
DECLARE #LongDescDirty bit = 0
Declare #old varchar(4000) = (SELECT LongDescription from deleted)
Declare #new varchar(4000) = (SELECT LongDescription from inserted)
if (#old <> #new)
BEGIN
SET #LongDescDirty = 1
END
Update table
Set LongDescUpdated = #LongDescUpdated
.....