Using trigger in one table and updating other table - sql

CREATE TRIGGER dbo.YourTrigger
ON a
AFTER UPDATE
AS
BEGIN
SET NOCOUNT ON;
IF NOT UPDATE(name)
RETURN
UPDATE d
set upload = 1
FROM d
END
This is the code, but it's not working the way i want it. in this case its updating my upload field from Table (d) when every any record change in table (a) .
i want upload field in table (d) to be change only when (name field) change in Table (a).

You use the special Inserted and Deleted tables inside a trigger to identify which rows have been affected. For an update trigger, Deleted contains the "before" version of the rows and Inserted contains the "after" version of the rows.
CREATE TRIGGER dbo.YourTrigger
ON a
AFTER UPDATE
AS
BEGIN
SET NOCOUNT ON;
IF UPDATE(name)
UPDATE d
set upload = 1
FROM Inserted i
INNER JOIN Deleted de
ON i.EmpId= de.EmpId
INNER JOIN d
ON i.EmpId= d.RecId
WHERE i.name <> de.name
END

Why dont you do it a little cleaner and simple since you are only going to update if name is updated...
CREATE TRIGGER dbo.YourTrigger
ON a
AFTER UPDATE
AS
BEGIN
SET NOCOUNT ON;
IF UPDATE(name)
BEGIN
UPDATE d
set upload = 1
FROM d
END
ELSE
BEGIN
--HERE GOES CODE
END
END

Related

Trigger running every time despite conditional statement

I am trying to write an update trigger on a table which would cause it to run an additional update statement only if a certain column has been changed, so far the trigger runs the update no matter what, hoping maybe someone can see what I am doing wrong here.
Here is the trigger.
ALTER TRIGGER [dbo].[StatusChangedUpdateTrigger]
ON [dbo].[Trans_Order]
AFTER UPDATE
AS
DECLARE #OldOrderStatusId INT, #NewStatusOrderId INT, #ERRNUM INT;
BEGIN
SET #OldOrderStatusId = (SELECT OrderStatusId FROM deleted);
SET #NewStatusOrderId = (SELECT OrderStatusId FROM inserted);
IF (#OldOrderStatusId != #NewStatusOrderId)
SET NOCOUNT ON;
UPDATE Trans_Order
SET StatusChanged = 1
WHERE Id = (SELECT ID FROM inserted)
END
For some reason this is running no matter what, I can never set StatusChanged to 0 as it will automatically flip it back to 1 even if the OrderStatusId hasn't changed. So my update statement is running no matter what, so I am guessing I am doing something wrong in the if statement.
Hmmmm . . . Your logic seems strange. I would expect:
UPDATE t
SET StatusChanged = 1
FROM Trans_Order t JOIN
Inserted i
ON t.id = i.id JOIN
Deleted d
ON t.id = d.id
WHERE i.OrderStatusId <> d.OrderStatusId;
You might need to take NULL values into account -- although your code does not.
Note that your code is just a bug waiting to happen, because it assumes that inserted and deleted have only one row.
The specific problem with your code is that it is really:
IF (#OldOrderStatusId != #NewStatusOrderId)
BEGIN
SET NOCOUNT ON;
END;
UPDATE Trans_Order
SET StatusChanged = 1
WHERE Id = (SELECT ID FROM inserted);
Your indentation has confused the logic. However, you should still use the set-based version so the trigger does not fail.
The correct way to approach your trigger is as follows:
create or alter trigger [dbo].[StatusChangedUpdateTrigger] on [dbo].[Trans_Order]
after update
as
set nocount on
if ##RowCount=0 return
if Update(OrderStatusId)
begin
update t
set statusChanged=1
from inserted i join deleted d on d.id=i.id and d.OrderStatusId != i.OrderStatusId
join Trans_Order t on t.id=i.id
end
Always test ##rowcount and return if no rows updated.
Always put set options before DML
As you are only looking to update if a specific column is updated you can test specifically for that and if the update statement that's run doesn't touch that column the trigger will not run.
This will correctly account for multiple rows being updated and only update those where the new value is different to the old value.

Delete trigger and getting field from another table

I have this delete trigger on an SQL database. The record deletes currently and gets written to an audit table. I have been asked to include in this history table a field from another table that is related to the record being deleted based on SurveyID. I thought I could do something like
select #Status = Status from table where Survey = deleted.Survey
But this is incorrect syntax.
ALTER trigger [dbo].[table_Selfdelete]
on [dbo].[table]
after delete
as
Begin
Set nocount on;
Declare #SurveyId int
Declare #StudentUIC varchar(10)
Declare #Status varchar(10)
select #SurveyId = deleted.SurveyID,
#StudentUIC = deleted.StudentUIC
from deleted
select #Status = Status from tbly when SurveyID = deleted.SurveyID
insert into fupSurveyAudit
values(#SurveyId,#StudentUIC,#Status)
End
Arrgh. I think you want this insert in your trigger (and nothing else):
insert into fupSurveyAudit(SurveyId, StudentUIC, status)
select d.SurveyId, d.StudentUIC, y.status
from deleted d left join
tbly y
on d.SurveyId = y.SurveyId;
Notes:
deleted could contain more than one row, so assuming that it has one row can lead to a run-time error or incorrect results.
A left join is needed in case there is no matching row for the status.
You should always include the columns in an insert
Your archive table should have additional columns, such as an identity column and the date of the insert, which are set automatically (and hence not explicitly part of the insert).
Triggers are fired once for each statement (Delete,insert,update) not for each row inside the statement.
You cannot use variables here because when multiple lines are deleted from the table only one line will be inserted in the Audit table because the variable can only hold one value.
You just need a simple insert from the deleted table into the Audit table something like this....
ALTER trigger [dbo].[table_Selfdelete]
on [dbo].[table]
after delete
as
Begin
Set nocount on;
insert into fupSurveyAudit(SurveyId, StudentUIC,[Status])
select d.SurveyID
,d.StudentUIC
,y.[Status]
from deleted d
INNER JOIN tbly y ON y.SurveyID = deleted.SurveyID
End
Try this
ALTER trigger [dbo].[table_Selfdelete]
on [dbo].[table]
after delete
as
Begin
Set nocount on;
insert into fupSurveyAudit -- Better listed the column list here
select
d.SurveyID, d.StudentUIC, y.Status
from
deleted d JOIN tbly y ON d.SurveyID = y.SurveyID
End

SQL Server : create trigger to replace old value to new value on another table

I am using SQL Server 2008. I want to create a trigger for update which will fire on update of user table.
Trigger functionality: replace user_tbl updated mobile number to user_work_tbl.
CREATE TRIGGER [dbo].[tr_User_Modified]
ON [dbo].[user_tbl]
AFTER UPDATE
AS BEGIN
SET NOCOUNT ON;
DECLARE #MobileNo varchar(11)
IF UPDATE (mobile_no)
BEGIN
DECLARE #MobileNo VARCHAR(50)
SELECT #MobileNo = mobile_no
FROM [dbo].user_tbl
UPDATE [dbo].[user_work_tbl]
SET mobile_no = #MobileNo
WHERE [dbo].[user_work_tbl].mobile_no = #oldMobileNo // here I have a problem
END
END;
In the comment "here I have a problem" I need a mobile number which exists in user_tbl before update so that the only row of user_work_tbl gets updated.
Any suggestions to do this are also accepted.
Thanks for your all response
You need to join three tables together in your trigger - user_work_tbl, inserted and deleted. However, its not clear at the moment exactly what conditions are required:
CREATE TRIGGER [dbo].[tr_User_Modified]
ON [dbo].[user_tbl]
AFTER UPDATE
AS BEGIN
SET NOCOUNT ON;
IF UPDATE (mobile_no)
BEGIN
UPDATE u
SET mobile_no=i.mobile_no
FROM user_work_tbl u
inner join
deleted d
on u.mobile_no = d.mobile_no
inner join
inserted i
on
i.PKCol = d.PKCol --What's the PK of user_tbl?
END
END;
inserted and deleted are pseudo-tables that contain the new and old rows that were affected by a particular statement, and have the same schema as the original table. They're only accessible from within the trigger.
Note, also, that the above trigger is correct, even when multiple rows are updated in user_tbl - provided you can correctly relate inserted and deleted in the final ON clause.
You can get the old phone number from the table deleted and the new one from inserted, but you should use user primary key the update the rows.

Executing a trigger; updating another field

I have been reading up on triggers, and I don't seem to be finding an example, that handles my situation. My situation is unfortunate. The previous DBA scattered redundant data throughout our database.
I'd like to update the company name in multiple other tables once the company name has been changed in my organiz table. I have this, but it doesn't seem to work:
CREATE TRIGGER updOrgNameTrigger
ON organiz
AFTER UPDATE
AS
IF UPDATE(Org_Name_1)
BEGIN
DECLARE #org_name varchar(256)
SET #org_name = (select Org_Name_1 from organiz)
UPDATE other_table set Org_Name_1 = #org_name
UPDATE the_other_table set Org_name_1 = #org_name
END
Is what I am trying to do possible?
Your current trigger assumes that an update can only ever affect a single row; it also intends to update every single row in the other two tables with an arbitrary value from the source table (not necessarily the row that was updated!). You need to use the inserted pseudo-table to identify the row(s) that fired the trigger and to pull the new value(s) for the Org_Name_1 column. How about this version:
CREATE TRIGGER dbo.updOrgNameTrigger
ON dbo.organiz
AFTER UPDATE
AS
BEGIN
SET NOCOUNT ON;
UPDATE o SET Org_Name_1 = i.Org_Name_1
FROM dbo.other_table AS o
INNER JOIN inserted AS i
ON o.org_id = i.org_id;
UPDATE o2 SET Org_Name_1 = i.Org_Name_1
FROM dbo.the_other_table AS o2
INNER JOIN inserted AS i
ON o2.org_id = i.org_id;
END
GO

Basic SQL update trigger

I want to create a trigger that runs just before a row in a table is updated, and writes all the fields in the row before it is updated to an archive table. What would be the correct syntax required to gain access to the row fields before the update so that I can write them into my archive table?
EDIT :
So this should do what I want, but it doesn't seem to work. I get the error 'there is already an object called config_SystemSettings in the database :
CREATE TRIGGER [config].[UpdateSystemSettings]
ON [config].[SystemSetting]
AFTER UPDATE
AS
BEGIN
SET NOCOUNT ON;
SELECT old.settingId, old.campId, old.settingKey, old.settingValue
into [history].[config_SystemSettings]
FROM [config].[SystemSetting] AS old
INNER JOIN deleted AS del ON del.settingId = old.settingId
END
GO
SELECT ... INTO always wants to create a new table - so use INSERT ... SELECT instead:
CREATE TRIGGER [config].[UpdateSystemSettings]
ON [config].[SystemSetting] AFTER UPDATE AS BEGIN
SET NOCOUNT ON;
insert into [history].[config_SystemSettings] (settingId,campId,settingKey,settingValue)
SELECT old.settingId, old.campId, old.settingKey, old.settingValue
FROM [config].[SystemSetting] AS old
INNER JOIN deleted AS del ON del.settingId = old.settingId
But you will have to explicitly create [history].[config_SystemSettings] first.