今天说一下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 ( N'a' ) 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 = N'TR_AAA3_7', -- nvarchar(517) @order = 'first', -- varchar(10) @stmttype = 'INSERT', -- varchar(50) @namespace = NULL -- varchar(10) EXEC sys.sp_settriggerorder @triggername = N'TR_AAA3_4', -- nvarchar(517) @order = 'last', -- varchar(10) @stmttype = 'INSERT', -- varchar(50) @namespace = NULL -- varchar(10) INSERT INTO dbo.AAA3 ( Name ) VALUES ( N'a' ) 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 ( N'a' ) TRIGGER7 TRIGGER1 TRIGGER2 TRIGGER3 TRIGGER5 TRIGGER6 TRIGGER8 TRIGGER4 (1 行受影响) Instead 1 TRIGGER7 TRIGGER1 TRIGGER2 TRIGGER3 TRIGGER5 TRIGGER6 TRIGGER8 TRIGGER4 (1 行受影响) Instead 1
就是说instead of 触发器执行是会在 after触发器之后??我怀疑是因为创建时间问题。然后反过来先创建 instead of 触发器,发现执行顺序也是 这样纸。
恕我眼拙,在触发器介绍的文档里面也没有找到这个描述。还是各位不吝赐教