SQL Server : AFTER INSERT trigger and INSERT INTO - sql-server

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.

Related

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

How to insert into another table if one of two columns has been updated in Trigger?

I am trying to insert values into another table with an after update trigger in the SQL server.
I have a table where I am storing my employees (employee_id, name, exam_results, exam_date) and I need to make a trigger that allows me to insert employee_id, exam_results, and exam_date into a table called exams_backlog whenever exam_results or exam_date is updated in table employees.
I don't know if I am able to check those fields to make the insert.
This is what I have so far:
CREATE TRIGGER updateExamBacklogTrigger
ON employees
AFTER UPDATE
AS
BEGIN
*****HERE IS WHERE I NEED TO CHECK IF ONE OF THOSE TWO FIELDS HAS BEEN UPDATED*****
INSERT INTO exams_backlog SELECT e.employee_id, e.exam_results, e.exam_date FROM employees e
SET NOCOUNT ON;
END
GO
Thanks in advance.
I have found the solution I've been looking for:
As I wanted to check if exam_results or exam_date had been updated I have used
IF(UPDATE(exam_results) OR UPDATE(exam_date ))
And then in order to only insert data for those employees that had been updated I used an
INNER JOIN inserted i ON i.employee_id = e.employee_id
So the complete trigger results as this:
CREATE TRIGGER updateExamBacklogTrigger
ON employees
AFTER UPDATE
AS
BEGIN
IF(UPDATE(exam_results) OR UPDATE(exam_date ))
INSERT INTO exams_backlog SELECT e.employee_id, e.exam_results, e.exam_date FROM employees e INNER JOIN inserted i ON i.employee_id = e.employee_id
SET NOCOUNT ON;
END
GO

How to set trigger based on update query in 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;

Update trigger that only stores information if data is actually updated?

CREATE TRIGGER AuditTrigger2
ON authors
AFTER UPDATE
AS
INSERT INTO audit (trackingUser, date_time)
VALUES (SYSTEM_USER, getdate())
GO
What do I need to add to my update trigger for it to exclude update attempts that don't actually update anything?
Also my audit table has a column for transaction type but I am unsure of how to get the transaction type from the trigger and insert it into that column.
INSERT INTO audit (trackingUser, date_time)
SELECT SYSTEM_USER, getdate()
FROM Inserted I
INNER JOIN Deleted D on D.id = I.id /* Use your PK condition */
WHERE <some condition that compares columns in I & D>
EDIT: Based on your comment you may want:
CREATE TRIGGER AuditTrigger2 ON authors
AFTER INSERT, UPDATE, DELETE
AS
BEGIN
-- Handle Insert
INSERT INTO audit (trackingUser, date_time, trasactionType)
SELECT SYSTEM_USER, getdate(), 'inserted'
FROM Inserted I
WHERE NOT EXISTS (SELECT 1 FROM Deleted)
AND <some condition that compares columns in I & D>
-- Handle Delete
INSERT INTO audit (trackingUser, date_time, trasactionType)
SELECT SYSTEM_USER, getdate(), 'deleted'
FROM Deleted I
WHERE NOT EXISTS (SELECT 1 FROM Inserted)
AND <some condition that compares columns in I & D>
-- Handle Update
INSERT INTO audit (trackingUser, date_time, trasactionType)
SELECT SYSTEM_USER, getdate(), 'updated'
FROM Inserted I
INNER JOIN Deleted D ON D.id = I.id /* Use your PK condition */
WHERE <some condition that compares columns in I & D>
END
GO
Note: <some condition that compares fields in I & D> is to exclude attempts which don't update anything, so you would have to compare every column in the table to see if its changed or not. Inserted is a temp table which contains the new values, Deleted is a temp table which contains the old values.

SQL Trigger Insert on Create convert column

I am trying to create a trigger to insert a record into one table when a record is created in another table. I have figured out how to do this however I am trying to figure out how to change a value of one of the columns value.
In the originating table I have 'County' and in the second table I have a 'CountyID' that comes from a 'County' table. How would I take the 'County' and convert it into a 'CountyID'?
My trigger so far -
CREATE TRIGGER [dbo].[AQB_RMS_LocationCreate] on [AVData].[dbo].[SourceSite]
AFTER INSERT
AS
BEGIN
INSERT INTO AQB_MON.[AQB_RMS].[Location]
([LocationName],[Latitude],[Longitude],[Enabled]
,[StreetAddress1],[StreetAddress2],[City],[CountyID],[StateAbbr],[ZipCode],[DATE_CREATED])
SELECT i.[Description],i.[Latitude],i.[Longitude],i.[Enabled]
,i.[StreetAddress1],i.[StreetAddress2],i.[City],i.[County],i.[StateRegion],i.[ZipCode], getdate()
from [AVData].[dbo].[SourceSite] ss
inner join inserted i on ss.SourceSiteID = i.SourceSiteID
END
GO
Wouldn't this work?
CREATE TRIGGER [dbo].[AQB_RMS_LocationCreate] on [AVData].[dbo].[SourceSite]
AFTER INSERT
AS
BEGIN
INSERT INTO AQB_MON.[AQB_RMS].[Location]
([LocationName],[Latitude],[Longitude],[Enabled]
,[StreetAddress1],[StreetAddress2],[City],[CountyID],[StateAbbr],[ZipCode],[DATE_CREATED])
SELECT i.[Description],i.[Latitude],i.[Longitude],i.[Enabled]
,i.[StreetAddress1],i.[StreetAddress2],i.[City],C.CountyId,i.[StateRegion],i.[ZipCode], getdate()
from [AVData].[dbo].[SourceSite] ss
inner join inserted i on ss.SourceSiteID = i.SourceSiteID
inner join dbo.County C on C.County = i.County
END

Resources