首页 > 解决方案 > ROLLBACK 使 INSERTED 表中的数据在 AFTER INSERT TRIGGER 中删除

问题描述

我举一个例子来说明我的问题。我创建了一个这样的表:

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 = 1a

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表中的数据虽然已回滚,但不会被删除。

帮我深入解释一下触发器内部发生了什么?

标签: sql-servertriggerstransactionsinsertrollback

解决方案


据我所知,这是预期的行为。只是 AFTER 可能有点误导,具体取决于您如何看待它。

“触发器和触发它的语句被视为单个事务,可以从触发器内部回滚。如果检测到严重错误,则整个事务会自动回滚。”。

https://msdn.microsoft.com/en-us/library/ms178110.aspx


推荐阅读