"after trigger"可以完全被"instead of trigger"代替吗?

Can "after trigger" be replaced completely by "instead of trigger"?

我知道基本的触发器概念,并且在学习时玩过它。我没有太多实践经验,因为我很少使用它。现在我的问题是,所有after trigger都可以完全替换为instead trigger吗?

对我来说 而不是触发器 是一种 "before trigger",它会在操作发生之前触发。所以我们可以做一些有用的事情,或者回滚事务。既然我们无所不能,我们就可以INSERT, UPDATE, DELETE。对我来说,我似乎可以使用 而不是 trigger 来完全替换 after trigger。是真的吗?

下面是针对 SQL 服务器的示例。这两个触发器的目的是防止删除。似乎他们两个都有效。

USE test;
GO
IF OBJECT_ID(N'dbo.a', N'U') IS NOT NULL
    DROP TABLE dbo.a;
GO

CREATE TABLE dbo.a (id INT, c1 INT);
GO

INSERT  INTO a
VALUES  (1, 1);
GO

-- instead of trigger
IF OBJECT_ID('dbo.t1', 'TR') IS NOT NULL
    DROP TRIGGER dbo.t1;
GO
CREATE TRIGGER dbo.t1 ON dbo.a
    INSTEAD OF DELETE
AS
BEGIN
    ROLLBACK;
    PRINT 't1: Not allowed to delete data  from dbo.a';
END
GO


-- delete a row from the table to test the trigger
DELETE  FROM a
WHERE   id = 1;
-- and it works!

-- drop the first trigger
IF OBJECT_ID('dbo.t1', 'TR') IS NOT NULL
    DROP TRIGGER dbo.t1;
GO

-- create an after trigger
IF OBJECT_ID('dbo.t2', 'TR') IS NOT NULL
    DROP TRIGGER dbo.t2;
GO
CREATE TRIGGER dbo.t2 ON dbo.a
    AFTER DELETE
AS
BEGIN
    ROLLBACK;
    PRINT 't2: Not allowed to delete data  from dbo.a';
END
GO


-- delete a row from the table to test the trigger
DELETE  FROM a
WHERE   id = 1;
-- and it works!


-- drop the second trigger
IF OBJECT_ID('dbo.t2', 'TR') IS NOT NULL
    DROP TRIGGER dbo.t2;
GO

是的,它们可以等效,除非您必须记住在后触发器中已经发生了操作 - 通常由您通过回滚来撤消它。

在代替触发器中,操作尚未发生,由您(在触发器中)执行操作。后触发通常作为审计步骤完成。通常使用 instead of 来防止某些事情发生。

已删除和已插入的 table 在任何一种情况下都会被填充。

你可以通过下面的代码来验证我刚才说的:

删除 table dbo.t1

创建table dbo.t1 (i1 int)

插入 dbo.t1 值 (1),(5), (6)

select * 来自 dbo.t1

; 去

在 dbo.t1 上创建触发器 dbo.t2trig
删除后 AS

开始

select * from deleted

print 'in after trigger dbo.t1trig'

结束

从 dbo.t1 中删除 i1 < 6

select * 来自 dbo.t1

插入 dbo.t1 值 (1),(5)

select * 来自 dbo.t1

; 去

删除触发器 dbo.t2trig

; 去

在 dbo.t1 上创建触发器 dbo.t2trig
而不是删除 AS

开始

select * from deleted

print 'in trigger instead of dbo.t1trig'

结束

插入 dbo.t1 值 (1),(5)

从 dbo.t1 中删除 i1 < 6

select * 来自 dbo.t1