How to set trigger based on update query in SQL Server? - sql-server

I am trying to set trigger whenever phone is updated in table1 and then do operation like check phone from table2 and if present, pick up the employee code from table2 and then update employee code in table1.
My code for trigger:
CREATE TRIGGER UPDATED_Contact_Trigger
ON table1
AFTER UPDATE
AS
DECLARE #tuid bigint;
DECLARE #phone varchar(15);
DECLARE #employee_code varchar(10);
IF (UPDATE (phone)) --Phone is the Column Name
BEGIN
SELECT #employee_code = i.emp_code
FROM table2 i (nolock)
WHERE i.MOBILE_NO = #phone
UPDATE table1
SET client_code = #employee_code
WHERE tuid= #tuid
END;
This trigger is set, but there is no update on table1 even if I update a contact which is present in table2

You're not even looking at the Inserted or Deleted pseudo tables in your code - how do you want to know what rows have been updated??
Inserted is a pseudo table that contains all updated rows - and it contains the new values after the update operation, while Deleted contains the same rows, but with the old values before the update.
You need to do something like this:
join your Table1 to Inserted to get the rows that were updated (since you didn't show your table structure, I cannot know what your primary key on Table1 is - you need to use that to join to Inserted)
add a join to your Table2 and pick those rows that have been updated, and limit those to the ones that have been updated in the Phone column (by comparing the Inserted.Phone value to Deleted.Phone)
Try this code:
CREATE TRIGGER UPDATED_Contact_Trigger
ON table1
AFTER UPDATE
AS
BEGIN
-- update your base table
UPDATE t1
-- set the client_code to the employee_code from Table2
SET client_code = t2.employee_code
FROM dbo.Table1 t1
-- join to "Inserted" to know what rows were updated - use the primary key
INNER JOIN Inserted i ON t1.(primarykey) = i.(primarykey)
-- join to "Deleted" to check if the "Phone" has been updated (between Deleted and Inserted)
INNER JOIN Deleted d ON i.(primarykey) = d.(primarykey)
-- join to "Table2" to be able to fetch the employee_code
INNER JOIN dbo.Table2 t2 ON t2.mobile_no = t1.phone
-- ensure the "Phone" has changed, between the old values (Deleted) and new values (Inserted)
WHERE i.Phone <> d.Phone;
END;

Related

SQL Server : AFTER INSERT trigger and INSERT INTO

I want to create a trigger that will fill up my sales history base after firing in the ORDER table.
I am creating a specific order in regular data base and after that this order automatically goes to sales_history database.
Below part works properly.
When I create a new order in regular database my sales_history database is growing with new ID_ORDERS, hooray! :)
ALTER TRIGGER [dbo].[InsertTrig]
ON [dbo].[ORDER]
AFTER INSERT
AS
IF EXISTS (SELECT *
FROM inserted i
WHERE i.ID_TYPE = 1) -- specific order type
BEGIN
INSERT INTO id.dbo.sales_history (id_order)
SELECT i.ID_ORDER FROM inserted i
END
The problem arises when I want join another table. The trigger stops working
ALTER TRIGGER [dbo].[InsertTrig]
ON [dbo].[ORDER]
AFTER INSERT
AS
IF EXISTS (SELECT *
FROM inserted i
WHERE i.ID_TYPE = 1) -- specific order type
BEGIN
INSERT INTO id.dbo.sales_history (id_order, id_item)
SELECT
inserted.ID_ORDER, ORDER_DETAILS.ID_ITEM
FROM
inserted
INNER JOIN
ORDER_DETAILS ON ORDER_DETAILS.ID_ORDER = inserted.ID_ORDER
END
I also tried this way, and still nothing :(
ALTER TRIGGER [dbo].[InsertTrig]
ON [dbo].[ORDER]
AFTER INSERT
AS
IF EXISTS (SELECT *
FROM inserted i
WHERE i.ID_TYPE = 1) -- specific order type
BEGIN
DECLARE #xyz AS numeric(18, 0)
SET #xyz = (SELECT inserted.ID_ORDER FROM inserted)
INSERT INTO id.dbo.sales_history (id_order, id_item)
SELECT
ORDER.ID_ORDER, ORDER_DETAILS.ID_ITEM
FROM
ORDER
INNER JOIN
ORDER_DETAILS ON ORDER_DETAILS.ID_ORDER = ORDER.ID_ORDER
WHERE
ORDER.ID_ORDER = #xyz
END
I want to create a trigger that will automatically fill up my sales history base after firing in ORDER table.
Your trigger is on the Order table, meaning SQL Server fires it after you insert records into the Order table. At which point, the relevant records in the Order_Details table couldn't have been inserted yet, because they have a foreign key to the Order table.
This is why an inner join between your inserted table and the Order_details table returns 0 rows.
If you want your sales_history from the order_details table, you have to populate it after you insert the records to the order_details table.
CREATE OR ALTER TRIGGER [dbo].[OrderDetails_AfterInsert]
ON [dbo].[ORDER_DETAILS]
AFTER INSERT
AS
INSERT INTO id.dbo.sales_history (id_order, id_item)
SELECT
inserted.ID_ORDER, inserted.ID_ITEM
FROM
inserted
INNER JOIN
[ORDER] ON [ORDER].ID_ORDER = inserted.ID_ORDER
WHERE [ORDER].ID_TYPE = 1 -- specific order type
As a side note: InsertTrig is bad name. Note the name of the trigger in my answer - it tells you exactly what this trigger is for, and on what table.

Creating Trigger to get data from one table to another and generating a timestamp

I am trying to track Inventory where data would be entered in an Excel sheet (SQL Spreads) and then updates the SQL table and then gather the sum of that data and put it onto another table that would then generate a timestamp to when it was changed/updated/inserted.
The Pictures with highlighted columns is where I want to have the data in.
(TotalBinLo --> Binlocation)
and then when Binlocation is populated (inserted/updated/deleted) generating a timestamp (MM/DD/YYYY HH:MM:SS)
This is what I've come up so far.
---This Trigger is working when pulling data from one table into another--
Create Trigger tr_BC_totalbinLoc
on bincount
After Update
AS
Begin
update OnHandInv
set OnHandInv.binlocation = bincount.totalbinlo
from bincount
inner join OnHandInv on bincount.partnumber = OnHandInv.PartNumber;
End
---Another Trigger (Works) but enters in date for all rows. (Don't want) (only need for one column.)
Create Trigger tr_totalbinLoc_OHI
On Onhandinv
After Update
AS
Update Onhandinv
set dateupdated = getutcdate()
where PartNumber in (select distinct PartNumber from onhandinv)
totalbinlo
ColNeedToPopu
You need to join the inserted table to OnHandInv. I have assumed that PartNumber is the primary key to join on.
You also need to remove deleted rows which exactly match, in other words rows where no change has actually been made.
CREATE OR ALTER TRIGGER tr_BC_totalbinLoc
ON bincount
AFTER UPDATE
AS
SET NOCOUNT ON;
IF NOT EXISTS (SELECT 1 FROM inserted)
RETURN;
UPDATE o
SET
binlocation = i.totalbinlo
dateupdated = getutcdate()
FROM (
SELECT partnumber, totalbinlo
FROM inserted i
EXCEPT
SELECT partnumber, totalbinlo
FROM deleted d
) i
INNER JOIN OnHandInv o ON i.partnumber = i.PartNumber;
GO

(TRIGGER) if cell1 = 'value' THEN INSERT INTO table (date) VALUES (CURRENT_TIMESTAMP)

I need to create a trigger in SQL Server that triggers every time that the value from column "status" = 'Baja'
CREATE TRIGGER trg_triggerName
ON dbo.table1
AFTER UPDATE
AS
BEGIN
IF status = 'Baja' THEN BEGIN
INSERT INTO dbo.table1 (fechaBaja)
VALUES (CURRENT_TIMESTAMP)
END
END
GO
I got this error message
Msg 207, Level 16, State 1, Procedure trg_FechaBaja, Line 3 [Batch Start Line 34]
Invalid column name 'status'.
IF status = 'Baja' THEN BEGIN
In this line the "status" give me the message "invalid column name 'status'" and I'm 100% sure that my column has that name.
IN RESUME: Got a table named table1 that has a column named 'status' and another column named 'fechaBaja'
Every time that the 'status' value changes to 'Baja', I need to trigger and update the cell 'fechaBaja' with the current_timestamp
All the operations are in the same table1.
First, you want an update, not an insert.
Second, A trigger in SQL Server is fired once per statement, not once per row. This means that if the update statement that fired the trigger have updated multiple rows, your trigger will be fired once, and include data about these rows in the inserted and deleted tables.
Third, You need to make sure that the update statement inside the trigger will not raise it again. Do that by configuring the database.
The code you need is something like this:
CREATE TRIGGER trg_triggerName ON dbo.table1
AFTER UPDATE AS
BEGIN
UPDATE t
SET fechaBaja = CURRENT_TIMESTAMP
FROM dbo.table1 As T
INNER JOIN Inserted As I
ON T.<PrimaryKey> = I.<PrimaryKey>
INNER JOIN Deleted As D
ON T.<PrimaryKey> = D.<PrimaryKey>
WHERE I.[status] = 'Baja'
AND (D.[Status] IS NULL OR D.[Status] <> 'Baja')
END
GO
I believe you want to update fechaBaja field if updated row status field equal'Baja'. You need to capture primary key information as well. I put 'Id' but you need to change it with your actuel field name.
CREATE TRIGGER trg_triggerName ON dbo.table1
AFTER UPDATE AS
BEGIN
UPDATE dbo.table1 SET fechaBaja=CURRENT_TIMESTAMP
WHERE EXISTS (SELECT 1 FROM INSERTED I WHERE dbo.table1.Id = I.Id AND I.Status='Baja')
END
GO
You can do it by joining the three tables like
CREATE TRIGGER trg_triggerName ON dbo.table1 AFTER UPDATE AS
BEGIN
UPDATE T1
SET T1.fechaBaja = CURRENT_TIMESTAMP
FROM dbo.table1 T1 INNER JOIN INSERTED T2 ON T1.ID = T2.ID
INNER JOIN DELETED T3 ON T1.ID = T3.ID
WHERE T2.[status] = 'Baja'
AND
(T3.[status] <> 'Baja' OR T3.[status] IS NULL);
END
GO
There is no need to use IF.
status is a reserved word, enclose it in brackets.
Join your table with INSERTED table to get all the IDs of the rows updated.
Join your table with DELETED table to get all the IDs where the data is not 'Baja'.
Filter by where INSERTED.[status] = 'Baja' AND DELETED.[status] <> 'Baja' to update only those rows.

Trigger for update table after update records in another table?

I need a trigger for update field on Table_2 when over any fields are Updated on table_1. I created one but when I update one record in table_1 on Table_2 it’s updating all fields.
Sample SQL:-
Create trigger trigger-1 ON Table_1 After Update
As
begin
SET NOCOUNT ON;
Insert into table_2 (Col1,col2,col3,..etc) Select (ins.column names)
from table_1
Suppose table_1 has many fields but still I need Updated fields. How to get only updated fields from table_1 to table_2 by using trigger?
Your syntax is wrong. You can use the inserted table. It contains all the column of the base table
INSERT INTO table_2 ( col1, col2, col3, . . .)
SELECT i.cola, i.colb, i.colc, . . .
FROM inserted i
if you need to know which columns are updated, use UPDATE( column name )
https://learn.microsoft.com/en-us/sql/t-sql/functions/update-trigger-functions-transact-sql
Finally, I found perfect answer.
In the case of an UPDATE, the
Deleted table will contain the old values, while the Inserted table
contains the new values after Update.
Based on requirement, if we want to all fields in trigger we need to mention all fields in the table and write something like:
For records after UPDATE:
CREATE TRIGGER trg_ProdUpdate
ON dbo.Production
AFTER UPDATE
AS
Begin
INSERT INTO dbo.Attribiute (ID, attributeValue, attributetype)
SELECT i.ID, i.prodrecord, i.prodvalue
FROM Production i
INNER JOIN INSERTED d ON i.ID = d.ID
For Records before UPDATE:
CREATE TRIGGER trg_ProdUpdate
ON dbo.Production
AFTER UPDATE
AS
Begin
INSERT INTO dbo.Attribiute (ID, attributeValue, attributetype)
SELECT i.ID, i.prodrecord, i.prodvalue
FROM Attribiute i
INNER JOIN DELETED d ON i.ID = d.ID
We can join the Inserted and Deleted in to some History tables for audit by grabbing the Identical field (which is the same in both cases). The old value from the Deleted table, the new value from the Inserted table, and you store everything in the separate Table
For better understanding check this link Trigger insert old values- values that was updated

If Exists in trigger

Is there a way I can check if a value exists in a table I want to insert into activated by a trigger? If the value does exist, I want nothing to be done and if it doesn't I would like it to be inserted.
This is my current trigger
ALTER TRIGGER [dbo].[Update]
On [dbo].[A]
AFTER UPDATE
AS
Declare #Id int;
SELECT #Id = Issue FROM Inserted
INSERT INTO dbo.[B] (id, problem)
SELECT BugId, ProjectID
FROM dbo.[C]
WHERE BugId = #Id and (projectid = 547)
Many thanks
inserted can contain multiple rows. And left join can be your friend for testing for whether rows already exist:
ALTER TRIGGER [dbo].[Update]
On [dbo].[A]
AFTER UPDATE
AS
INSERT INTO dbo.[B] (id, problem)
SELECT BugId, ProjectID
FROM
dbo.[C]
inner join
inserted i
on
c.BugID = i.Issue
left join
dbo.B
on
B.ID = c.BugID
WHERE
C.projectid = 547 and B.BugID is null
You should do it as described in this SO post. Use an IF statement to check the existence.

Resources