SQL Trigger inserted deleted table contents on UPDATE - sql-server

I know from (Insert Update trigger how to determine if insert or update) that an UPDATE transaction causes rows in the deleted table
what are the contents of inserted and deleted when updating a single row?

Inserted contains that one row being updated with the new values (after the UPDATE), while Deleted contains that one row being updated with the old values (before the UPDATE)

Related

Why do upserted INSERTED.ID and DELETED.ID both contain values after MERGE?

Surprisingly, I can't find an answer to this on Google, although my terminology may be off. I also didn't see an explanation on MDSN.
Take the following code to perform a simple MERGE:
DECLARE #tbl_1 TABLE (ID int IDENTITY(1,1), person nvarchar(20));
DECLARE #tbl_2 TABLE (ID int IDENTITY(1,1), person nvarchar(20));
INSERT INTO #tbl_1 (person) VALUES ('Bob'),('Ted'),('Brian');
INSERT INTO #tbl_2 (person) VALUES ('Bob'),('Ted'),('Peter');
MERGE INTO
#tbl_2 as tgt
USING
#tbl_1 as src
ON
(tgt.person = src.person)
WHEN MATCHED THEN
UPDATE SET tgt.person = src.person
WHEN NOT MATCHED BY TARGET THEN
INSERT (person) VALUES (src.person)
WHEN NOT MATCHED BY SOURCE THEN
DELETE
OUTPUT
$ACTION,
DELETED.ID,
DELETED.person AS PersonOld,
INSERTED.ID,
INSERTED.person AS PersonNew;
In the results, I see that the ID value of each row is shown against both INSERTED and DELETED rows, where an UPDATE has taken place:
Why is this please? I would expect DELETED.ID to be NULL after an update, with INSERTED.ID representing the UPSERTED row (I have worked with triggers in the past, and assumed MERGE would follow the same approach).
Because MERGE as you seem to be aware is an UPSERT (update + insert).
Now, the INSERTED tables record information for rows added by INSERT & UPDATE comands and the DELETED table contains information for rows that were either updated or deleted.
Taking a look at the MSDN documentation on how to "Use the inserted and deleted Tables":
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.
and
An update transaction is similar to a delete operation followed by an
insert operation; the old rows are copied to the deleted table first,
and then the new rows are copied to the trigger table and to the
inserted table.
Update:
I saw you commented to your question that you realized that the operation is actually a delsert under the hood. And you might be thinking why would that be?
Think about how data is stored in SQL Server. It's stored on 8KB pages and when you update information in a column that is contained in a data page, the entire data page is being re-written, so essentially a delsert.
And the same thing with an INSERT, a new row will go in a data page (and might generate a page split - but that's another subject) and that entire data page will have to be re-written.

How to store record before it updated?

I use a SQL Server database. I have two tables Inspections and History_Inspections.
Before a record from the Inspections table is updated, I need to store it into the History_Inspections table.
I wanted to use a SQL Server update trigger but it fired only after the record is updated.
Any idea how can I store record from Inspections table in History_Inspections table before it updated ?
When an AFTER UPDATE trigger in SQL Server fires, the Inserted pseudo table inside the trigger contains the new values (after the UPDATE), and the Deleted pseudo table contains the old values (before the UPDATE).
So in your case, just read out the rows from the Deleted table and store those into your History_Inspections table.
CREATE TRIGGER trg_AfterUpdateInspections
ON dbo.Inspections
AFTER UPDATE
AS
INSERT INTO dbo.History_Inspections(list of columns)
SELECT (list of columns)
FROM Deleted

Capture updated rows in T-SQL

I don't write T-SQL code too often so how do I capture updated row in a trigger?
If I create a trigger for INSERT I can ask for records from inserted as in
Create Trigger [dbo].[tr_test]
on table1
for INSERT
as
declare #id int
select #id = i.RecordId from inserted as I
...
How do I do that for UPDATE?
There are are two trigger or magic tables in sql server that is inserted or deleted table.
If you are creating trigger for Insert
- data comes in only inserted table in deleted table there is no records find
Create Trigger [dbo].[tr_test]
on table1
for INSERT
as
if exists (select 1 from inserted) and not exists(select 1 from deleted)
-- Action which would you want For Insert
If you are creating trigger for Update
- updated data comes in only inserted table and previous data comes in deleted table there is no records find
Create Trigger [dbo].[tr_test]
on table1
for UPDATE
as
if exists (select 1 from inserted) and exists(select 1 from deleted)
-- Action which would you want when your target table has been update
If you are creating trigger for Delete
- Deleted data comes in Deleted table and in case of deleting data it not comes inserted table.
Create Trigger [dbo].[tr_test]
on table1
after Delete
as
if exists (select 1 from deleted ) and not exists(select 1 from inserted)
-- Action which would you want when your target table has been delete
The same way as with an insert trigger. In an update trigger, inserted contains the new values, and deleted contains the old.
Quoth the docs:
The deleted table stores copies of the affected rows during DELETE and UPDATE statements. During the execution of a DELETE or UPDATE statement, rows are deleted from the trigger table and transferred to the deleted table. The deleted table and the trigger table ordinarily have no rows in common.
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.
An update transaction is similar to a delete operation followed by an insert operation; the old rows are copied to the deleted table first, and then the new rows are copied to the trigger table and to the inserted table.
Source: DML Triggers, Use the inserted and deleted Tables

Using original record ID within trigger process

I have table question
id int
answers int
With every insert, delete call on this table I want to update answers column. I want to use trigger on this. I don't know how I can read question.id within trigger for insert, delete.
Any help appreciated.
Thanks.
In triggers that happen after insert, you can select from the inserted table to get the id of any inserted rows. Likewise for delete, you can select from the deleted table.
In BEFORE/AFTER INSERT trigger you can use OLD & NEW with "id" (OLD.id/NEW.id) and "answer" (OLD.answer/NEW.answer) columns. You will able to get OLD & NEW value of each column.
Similarly in AFTER DELETE trigger you can get OLD.id & OLD.answer, which in turn will give the deleted row's values

What should be the table contain updated row for update trigger

A while ago i read the article for Trigger in SQL Server, and it said that i can use the Logical Table "Updated" for updated rows... And i got error:
System.Data.SqlClient.SqlException: Invalid object name 'Updated'.
After a while of google, i found out some more post that said only 2 logical tables available are: Inserted and Deleted...
I'm confused... What should i use since my Trigger rely on the Updated table that contain the updated row, and use it to insert to another table or the same table with new PK...
Thank you very much
The two dummy tables are called Inserted (available in INSERT and UPDATE triggers) and Deleted (available in DELETE and UPDATE triggers).
There is no Updated dummy table in SQL Server triggers.
For an FOR UPDATE trigger, the Deleted table contains the old values, while the Inserted table contains the new ones.
Marc

Resources