我举了一个例子来说明我的问题。我创建了一个这样的表:
CREATE TABLE a
(
id INT
)
然后,我创建了一个AFTER INSERT
触发器,不允许将id = 1
插入表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
然后我将id = 1
插入表a
:
INSERT INTO a VALUES(1)
我从INSERTED
表什么也没得到。
我意识到,当我ROLLBACK时,表a
中的数据被回滚(我知道(,INSERTED
表中的数据也被删除。为什么?
如果我将AFTER INSERT
触发器更改为INSTEAD OF INSERT
触发器:
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)
然后我得到结果:
id
1
这意味着INSERTED
表中的数据虽然已被ROLLBACK,但并没有被删除。
帮我深入解释一下触发器内部发生了什么?
据我所知,这是预期的行为。只是AFTER可能有点误导,这取决于你如何看待它
"触发器和触发它的语句被视为单个事务,可以从触发器中回滚。如果检测到严重错误,整个事务将自动回滚。".
https://msdn.microsoft.com/en-us/library/ms178110.aspx