MSSQL如何让触发器在特殊语句执行时不触发

第一种方法:临时表

  1. 在需要禁用触发器的存储过程当中定义一个特殊名称的局部临时表
  2. 在触发器当中使用object_id(xxx)来检测是否存在来确定是否需要禁用触发器

第二种方法:context_info

理论基础

  1. context_info是局部的,类型是varbinary(128)的类型
  2. varbinary类型可以使用+来进行拼接,也就是说0x11+0x12=0x1112
  3. 可以使用substring函数来进行截断,截断之后的结果仍然是varbinary

实现方法

  1. 生成guid
  2. 在需要禁用触发器的存储过程当中将生成的guid拼接到context_info当中
  3. 在触发器当中检测这个guid是否存在,使用substring(context_info(),x,x)并判断是否和给定的二进制相等来实现(这里使用了上述第三点)
  4. 示例代码
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
create table test(id int not null primary key);

go
alter trigger trg_test_i
on test
after insert
as
begin
-- 判断guid值是否是需要禁用触发器的guid值
if SUBSTRING(CONTEXT_INFO(), 17,16) = 0x4722435B1BDD044C895DD7940015EE9F
return;
print 'insert';
end

-- 生成guid
declare @guid binary(16);
select @guid = CAST(NEWID() as binary(16));
print @guid;

go
declare @id varbinary(128);
set @id = cast(coalesce(SUBSTRING(CONTEXT_INFO(), 1, 16),replicate(0x00,16)) as binary(16)) +
CAST(0x4722435B1BDD044C895ED7940015EE9F as binary(16)) + 0x; -- 拼接context_info,其内部含有guid
set context_info @id; -- 传递
insert into test values(5);

第三种方法:使用session_context

这种方法只能在mssql 2016版本之后使用

实现方法

  1. 这种方式主要是引入了一个存储过程和一个函数
  2. 存储过程sp_set_session_context,用于设置键值(可以指定是否只读)
  3. 函数session_context(N'xxx')用于获取值,获取出来的值的类型是sql_variant,需要手动转换
  4. 注意键必须是unicode的,必须加N前缀