I am using a trigger on my table for update.
When I was updating 1 row, it works. But when I update 20 rows at once, the log only show 1 history update.
I want to show all updated rows. How to make it?
This my simple sql:
create trigger Triger_Update_Product
on product
for update
as begin
declare #first char(10)
declare #after char(10)
select #first = name from deleted
select #after = name from inserted
insert into historyproduk
select #first, #after, getdate()
end
You need to write the trigger in a set-based fashion and be aware that inserted and deleted will contain multiple rows - so these lines of code are really bad:
select #first = name from deleted
select #after = name from inserted
These select one arbitrary row from the update set - and they ignore all other rows. Don't do this!!
Try this instead:
create trigger Trigger_Update_Product
on product
for update
as begin
insert into historyproduk
select d.name, i.name, getdate()
from deleted d
inner join inserted i on d.PrimaryKey = i.PrimaryKey
end
You need to join the Inserted and Deleted pseudo tables on the primary key and then grab the Name from the old (deleted) and new (Inserted) and insert those - along with the date/time stamp - into the history table in a single INSERT ... SELECT .... statement to handle multiple rows being updated
Related
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.
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
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
I'm trying to create a trigger to copy newly added rows from one table on a different database but on the same server to another table and increment a column which only exists on the table where the new rows are being added. I'm not sure if the code is accurate and would like any feedback on how it can be improved.
CREATE TRIGGER AddReTncyTransStatement
ON [DBAdmin].[dbo].[ReTncyTransStatement]
AFTER UPDATE, INSERT
AS
BEGIN
INSERT INTO [DBAdmin].[dbo].[ReTncyTransStatement]
([ORG-CODE], [TNCY-SYS-REF], [TRANS-NO], [PROGRESS-RECID])
SELECT
[ORG-CODE],
[TNCY-SYS-REF],
[TRANS-NO],
[ANALYSIS-CODE] ``,
(SELECT MAX([PROGRESS-RECID])
FROM [DBAdmin].[dbo].[ReTncyTransStatement]) + 1 AS RECID
FROM
[SQLViewsPro2EOD].[dbo].[RE-TNCY-TRANS]
END;
I imagine that you have a table called [RE-TNCY-TRANS] which is in [SQLViewsPro2EOD] database and the other table which is [ReTncyTransStatement] that resides inside the [DBAdmin] database.
I also imagine that you want to insert a record into [ReTncyTransStatement] each time a record inserted into [RE-TNCY-TRANS]. So to achieve this you need to rewrite your trigger as below:
CREATE TRIGGER AddReTncyTransStatement
ON [SQLViewsPro2EOD].[dbo].[RE-TNCY-TRANS]
AFTER UPDATE, INSERT
AS
BEGIN
INSERT INTO [DBAdmin].[dbo].[ReTncyTransStatement]
(
[ORG-CODE],
[TNCY-SYS-REF],
[TRANS-NO],
[PROGRESS-RECID]
)
SELECT [ORG-CODE],
[TNCY-SYS-REF],
[TRANS-NO],
ISNULL((
SELECT MAX([PROGRESS-RECID]) FROM [DBAdmin].[dbo].[ReTncyTransStatement]
),0) + 1 AS RECID
FROM Inserted;
END;
Update
Why I used the ISNULL function?
Because at the first time, there is no record in [DBAdmin].[dbo].[ReTncyTransStatement] table, so the MAX([PROGRESS-RECID]) will be NULL. I used ISNULL to handle this situation.
Why I used the inserted?
According to the Microsoft docs:
The inserted table stores copies of the affected rows during INSERT
and UPDATE statements. During an insert or update transaction, new
rows are added to both the inserted table and the trigger table. The
rows in the inserted table are copies of the new rows in the trigger
table.
Read more here:https://learn.microsoft.com/en-us/sql/relational-databases/triggers/use-the-inserted-and-deleted-tables?view=sql-server-2017
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.