今天说一下DML触发器的顺序

Posted 神崎橙

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了今天说一下DML触发器的顺序相关的知识,希望对你有一定的参考价值。

因为05之后的版本允许了一个对象有多个after触发器,所以呢~顺序方面还是要留意一下下的。比如我现在要往一个测试表里面添加多个触发器。

技术分享
USE Test
GO 
CREATE TABLE AAA3 (ID INT IDENTITY(1,1),Name NVARCHAR(50))
GO

CREATE TRIGGER TR_AAA3_1 ON AAA3 FOR INSERT
AS
BEGIN 
    PRINT TRIGGER1
END
GO 

CREATE TRIGGER TR_AAA3_2 ON AAA3 FOR INSERT
AS
BEGIN 
    PRINT TRIGGER2
END
GO 

CREATE TRIGGER TR_AAA3_3 ON AAA3 FOR INSERT
AS
BEGIN 
    PRINT TRIGGER3
END
GO 

CREATE TRIGGER TR_AAA3_4 ON AAA3 FOR INSERT
AS
BEGIN 
    PRINT TRIGGER4
END
GO 

CREATE TRIGGER TR_AAA3_5 ON AAA3 FOR INSERT
AS
BEGIN 
    PRINT TRIGGER5
END
GO 

CREATE TRIGGER TR_AAA3_6 ON AAA3 FOR INSERT
AS
BEGIN 
    PRINT TRIGGER6
END
GO 

CREATE TRIGGER TR_AAA3_7 ON AAA3 FOR INSERT
AS
BEGIN 
    PRINT TRIGGER7
END
GO 

CREATE TRIGGER TR_AAA3_8 ON AAA3 FOR INSERT
AS
BEGIN 
    PRINT TRIGGER8
END
GO 
创建测试表和触发器

 

然后添加几条测试数据来看顺序

技术分享
INSERT INTO dbo.AAA3
        ( Name )
VALUES  ( Na )

GO 2

开始执行循环
TRIGGER1
TRIGGER2
TRIGGER3
TRIGGER4
TRIGGER5
TRIGGER6
TRIGGER7
TRIGGER8

(1 行受影响)
TRIGGER1
TRIGGER2
TRIGGER3
TRIGGER4
TRIGGER5
TRIGGER6
TRIGGER7
TRIGGER8
测试数据

 

可以看到是按照创建顺序来执行的。(官方提出表里面的各个触发器执行的顺序其实是无序的。只有在如果了第一条和最后一条执行触发器之后,才能保证这2个触发器的顺序,然而其它的触发器执行的顺序是无须的。)

然后我试下指定第一条和最后一条的位置。然后再进行测试。(是指定了触发器7第一,触发器4最后一个)。其它顺序也没变。

技术分享
EXEC sys.sp_settriggerorder @triggername = NTR_AAA3_7, -- nvarchar(517)
    @order = first, -- varchar(10)
    @stmttype = INSERT, -- varchar(50)
    @namespace = NULL -- varchar(10)

EXEC sys.sp_settriggerorder @triggername = NTR_AAA3_4, -- nvarchar(517)
    @order = last, -- varchar(10)
    @stmttype = INSERT, -- varchar(50)
    @namespace = NULL -- varchar(10)

INSERT INTO dbo.AAA3
        ( Name )
VALUES  ( Na )

GO 2

开始执行循环
TRIGGER7
TRIGGER1
TRIGGER2
TRIGGER3
TRIGGER5
TRIGGER6
TRIGGER8
TRIGGER4

(1 行受影响)
TRIGGER7
TRIGGER1
TRIGGER2
TRIGGER3
TRIGGER5
TRIGGER6
TRIGGER8
TRIGGER4
重新测试

看起来好像也不是无序啊~就和创建时间排序一致嘛~但是我认为还是不要抱这种错觉,这个版本是这样,没人能保证下一个版本还是这样哦!所以我觉得还是不要太相信这个特意做出来的测试例子。

如果需要查询触发器的状态。可以参考以下语句

SELECT a.name,a.object_id,a.is_disabled,a.is_instead_of_trigger,b.is_first,b.is_last,b.is_trigger_event FROM sys.triggers a
    INNER JOIN sys.trigger_events b ON a.object_id = b.object_id
    WHERE parent_id = OBJECT_ID(AAA3)

name                                                                                                                             object_id   is_disabled is_instead_of_trigger is_first is_last is_trigger_event
-------------------------------------------------------------------------------------------------------------------------------- ----------- ----------- --------------------- -------- ------- ----------------
TR_AAA3_1                                                                                                                        775673811   0           0                     0        0       1
TR_AAA3_2                                                                                                                        791673868   0           0                     0        0       1
TR_AAA3_3                                                                                                                        807673925   0           0                     0        0       1
TR_AAA3_4                                                                                                                        823673982   0           0                     0        1       1
TR_AAA3_5                                                                                                                        839674039   0           0                     0        0       1
TR_AAA3_6                                                                                                                        855674096   0           0                     0        0       1
TR_AAA3_7                                                                                                                        871674153   0           0                     1        0       1
TR_AAA3_8                                                                                                                        887674210   0           0                     0        0       1

 

最后我们乱入一个InsteatOf 触发器。看下执行顺序是怎么样。

技术分享
CREATE TRIGGER TR_AAA3_1_1 ON AAA3 INSTEAD OF INSERT
AS
BEGIN 
    INSERT INTO dbo.AAA3
            (  Name )
    SELECT Inserted.Name
        FROM Inserted
    PRINT Instead 1
END
GO 


INSERT INTO dbo.AAA3
        ( Name )
VALUES  ( Na )

TRIGGER7
TRIGGER1
TRIGGER2
TRIGGER3
TRIGGER5
TRIGGER6
TRIGGER8
TRIGGER4

(1 行受影响)
Instead 1

TRIGGER7
TRIGGER1
TRIGGER2
TRIGGER3
TRIGGER5
TRIGGER6
TRIGGER8
TRIGGER4

(1 行受影响)
Instead 1
测试instead of 触发器

 

就是说instead of 触发器执行是会在 after触发器之后??我怀疑是因为创建时间问题。然后反过来先创建 instead of 触发器,发现执行顺序也是 这样纸。

恕我眼拙,在触发器介绍的文档里面也没有找到这个描述。还是各位不吝赐教

 

以上是关于今天说一下DML触发器的顺序的主要内容,如果未能解决你的问题,请参考以下文章

今天简单说一下cdc 的使用

MySql触发器使用

MySQL触发器

当事务 DML 操作引发异常时,触发器中会发生啥

使用触发器对学生表操作进行日志记录

ORACLE触发器详解