I give an example to show my problem. I created a table like this:
CREATE TABLE a
(
id INT
)
I then created an AFTER INSERT
trigger to not allow insert id = 1
into table a
:
CREATE TRIGGER [dbo].[insert_a]
ON [dbo].[a] AFTER INSERT
AS
BEGIN
DECLARE @id INT
SELECT @id = id FROM inserted
IF @id = 1
BEGIN
RAISERROR('1', 12, 1)
ROLLBACK;
END
SELECT * FROM inserted
END
Then I insert id = 1
into table a
:
INSERT INTO a VALUES(1)
I get nothing from INSERTED
table.
I realize that when I ROLLBACK then + the data in table a
was rolled back (I know) and data in INSERTED
table is also removed. Why is that?
If I change the AFTER INSERT
trigger to an INSTEAD OF INSERT
trigger:
ALTER TRIGGER [dbo].[insert_a]
ON [dbo].[a] INSTEAD OF INSERT
AS
BEGIN
DECLARE @id INT
SELECT @id = id FROM inserted
IF @id = 1
BEGIN
RAISERROR('1', 12, 1)
ROLLBACK
END
SELECT * FROM inserted
END
INSERT INTO a VALUES(1)
Then I get the result:
id
1
That means data in INSERTED
table is not removed though have been ROLLBACK.
Help me explain deeply what happens inside trigger?
This is the intended behaviour as far as I know. It's just that AFTER may be a bit misleading depending on how you look at it.
"The trigger and the statement that fires it are treated as a single transaction, which can be rolled back from within the trigger. If a severe error is detected, the entire transaction automatically rolls back.".
https://msdn.microsoft.com/en-us/library/ms178110.aspx