SQL Server 2005:T-SQL临时禁用触发器

是否可以禁用一批命令的触发器,然后在批处理完成时启用它?

我确信我可以放弃触发器并重新添加它,但是我想知道是否有另一种方法。

DISABLE TRIGGER { [ schema_name . ] trigger_name [ ,...n ] | ALL } ON { object_name | DATABASE | ALL SERVER } [ ; ] 

http://msdn.microsoft.com/en-us/library/ms189748(SQL.90).aspx

其次是逆:

 ENABLE TRIGGER { [ schema_name . ] trigger_name [ ,...n ] | ALL } ON { object_name | DATABASE | ALL SERVER } [ ; ] 

http://msdn.microsoft.com/en-us/library/ms182706(SQL.90).aspx

有时从外部数据源填充空数据库或debugging数据库中的问题我需要禁用所有触发器和约束。 为此,我使用下面的代码:

禁用所有约束和触发器:

 sp_msforeachtable "ALTER TABLE ? NOCHECK CONSTRAINT all" sp_msforeachtable "ALTER TABLE ? DISABLE TRIGGER all" 

要启用所有约束和触发器:

 exec sp_msforeachtable @command1="print '?'", @command2="ALTER TABLE ? WITH CHECK CHECK CONSTRAINT all" sp_msforeachtable @command1="print '?'", @command2="ALTER TABLE ? ENABLE TRIGGER all" 

我不久前在SQLServerCentral上find了这个解决scheme,但是需要修改启用约束部分,因为原来的部分没有完全工作

但是,这样做几乎总是一个坏主意。 你会混淆数据库的完整性。 不要在没有考虑分支和检查dbas的情况下去做。

如果你确实按照马特的代码,一定要记得把扳机重新打开。 记住,在closures的时候,每个人都可以禁用触发器,不仅仅是为了你的进程,所以如果必须完成的话,那么在数据库最不活跃的时候(最好是在单用户模式下)。

如果您需要这样做来导入大量的数据,那么请考虑批量插入不触发触发器。 但是在批量插入之后,您的过程将不得不通过触发触发器来解决引入的任何数据完整性问题。

为了扩展Matt的答案,下面是MSDN上的一个例子。

 USE AdventureWorks; GO DISABLE TRIGGER Person.uAddress ON Person.Address; GO ENABLE Trigger Person.uAddress ON Person.Address; GO 

另一种方法是有效地禁用触发器,而不实际禁用触发器,并使用附加的状态variables并入触发器。

 create trigger [SomeSchema].[SomeTableIsEditableTrigger] ON [SomeSchema].[SomeTable] for insert, update, delete as declare @isTableTriggerEnabled bit; exec usp_IsTableTriggerEnabled -- Have to use USP instead of UFN for access to #temp @pTriggerProcedureIdOpt = @@procid, @poIsTableTriggerEnabled = @isTableTriggerEnabled out; if (@isTableTriggerEnabled = 0) return; -- Rest of existing trigger go 

对于状态variables,可以读取表中某种types的locking控制logging(最好是限于当前会话的上下文),可以使用CONTEXT_INFO(),或者使用特定的临时表名(它已经是会话作用域有限):

 create proc [usp_IsTableTriggerEnabled] @pTriggerProcedureIdOpt bigint = null, -- Either provide this @pTableNameOpt varchar(300) = null, -- or this @poIsTableTriggerEnabled bit = null out begin set @poIsTableTriggerEnabled = 1; -- default return value (ensure not null) -- Allow a particular session to disable all triggers (since local -- temp tables are session scope limited). -- if (object_id('tempdb..#Common_DisableTableTriggers') is not null) begin set @poIsTableTriggerEnabled = 0; return; end -- Resolve table name if given trigger procedure id instead of table name. -- Google: "How to get the table name in the trigger definition" -- set @pTableNameOpt = coalesce( @pTableNameOpt, (select object_schema_name(parent_id) + '.' + object_name(parent_id) as tablename from sys.triggers where object_id = @pTriggerProcedureIdOpt) ); -- Else decide based on logic involving @pTableNameOpt and possibly current session end 

然后禁用所有触发器:

 select 1 as A into #Common_DisableTableTriggers; -- do work drop table #Common_DisableTableTriggers; -- or close connection 

一个潜在的主要缺点是触发器会根据访问状态variables的复杂性而被永久放慢。

编辑:添加引用这个惊人的相似的2008年post塞缪尔·万加 。

 ALTER TABLE table_name DISABLE TRIGGER TRIGGER_NAME -- Here your SQL query ALTER TABLE table_name ENABLE TRIGGER TRIGGER_NAME 

不是批量编程的最佳答案,但对于其他人发现这个问题寻找一个快速简便的方法来暂时禁用触发器,这可以在SQL Server Management Studio中完成。

  1. 展开表格上的触发器文件夹
  2. 右键点击触发器
  3. 禁用

在这里输入图像说明

按照相同的过程重新启用。