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

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.

Related

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

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

SQL Insert, Update Trigger - Can you update the inserted table?

I have an SQL Trigger FOR INSERT, UPDATE I created which basically does the following:
Gets a LineID (PrimaryID for the table) and RegionID From the Inserted table and stores this in INT variables.
It then does a check on joining tables to find what the RegionID should be and if the RegionID is not equal what it should be from the Inserted table, then it should update that record.
CREATE TRIGGER [dbo].[TestTrigger]
ON [dbo].[PurchaseOrderLine]
FOR INSERT, UPDATE
AS
-- Find RegionID and PurchaseOrderLineID
DECLARE #RegionID AS INT
DECLARE #PurchaseOrderLineID AS INT
SELECT #RegionID = RegionID, #PurchaseOrderLineID = PurchaseOrderLineID FROM Inserted
-- Find PurchaserRegionID (if any) for the Inserted Line
DECLARE #PurchaserRegionID AS INT
SELECT #PurchaserRegionID = PurchaserRegionID
FROM
(...
) UpdateRegionTable
WHERE UpdateRegionTable.PurchaseOrderLineID = #PurchaseOrderLineID
-- Check to see if the PurchaserRegionID has a value
IF #PurchaserRegionID IS NOT NULL
BEGIN
-- If PurchaserRegionID has a value, compare it with the current RegionID of the Inserted PurchaseOrderLine, and if not equal then update it
IF #PurchaserRegionID <> #RegionID
BEGIN
UPDATE PurchaseOrderLine
SET RegionID = #PurchaserRegionID
WHERE PurchaseOrderLineID = #PurchaseOrderLineID
END
END
The problem I have is that it is not updating the record and I'm guessing, it is because the record hasn't been inserted yet into the PurchaseOrderLine table and I'm doing an update on that. But can you update the row which will be inserted from the Inserted table?
The major problem with your trigger is that it's written in assumption that you always get only one row in INSERTED virtual table.
SQL Server triggers are statement-triggers not row-triggers. You have to take that fact into consideration.
Now if I understand correctly the logic behind this trigger then you need just one update statement in it
CREATE TRIGGER TestTrigger ON PurchaseOrderLine
FOR INSERT, UPDATE
AS
UPDATE l
SET RegionID = u.PurchaserRegionID
FROM PurchaseOrderLine l JOIN INSERTED i
ON l.PurchaseOrderLineID = i.PurchaseOrderLineID JOIN
(
SELECT PurchaseOrderLineID, PurchaserRegionID
FROM UpdateRegionTable -- !!! change this for your proper subquery
) u ON l.PurchaseOrderLineID = u.PurchaseOrderLineID
For this example I've created a fake table UpdateRegionTable. You have to change it to the proper query that returns PurchaseOrderLineID, PurchaserRegionID (in your code you replaced it with ...). Make sure that it returns all necessary rows, not one.
Here is SQLFiddle demo
I think the problem could be that you are making the update to PurchaceOrderLine inside the trigger that is monitoring updates to the same table as well. Try to alter the trigger to just monitor the inserts, than if this works, you can make some changes or break your trigger on two: one for inserts, another for updates.
This has been resolved. I resolved the problem by adding the trigger to another table as the IF #PurchaserRegionID IS NOT NULL was always false.

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.