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


44

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

我确定我可以放弃触发器并重新添加它,但是我想知道是否有其他方法。

57
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

  0

谢谢!我认为我的SQL Server 2005 naivity在这个网站上表现得太好了。 23 9月. 082008-09-23 20:15:46

  0

不用担心;成为DBA很长一段时间,这些东西变成自动:) 23 9月. 082008-09-23 20:16:41

  0

即如果你使用该选项来修改触发器,并且脚本包含'ALTER TRIGGER [dbo]。[trgWhatever] ON [dbo]。[tblWhatever]'然后你需要'DISABLE TRIGGER [dbo]。[trgWhatever] ON [dbo]。[tblWhatever]'和'ENABLE TRIGGER [dbo]。[trgWhatever] ON [dbo]。[tblWhatever]' 22 9月. 152015-09-22 14:45:41

  0

注意 - 我得到一个错误'Incorrect syntax靠近'DISABLE'。''除非我在'PRINT'之间放置一个';'一些信息'; DISABLE TRIGGER [dbo] .....' 23 9月. 152015-09-23 15:22:06


15

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

如果你确实按照马特的代码,一定要记得把扳机重新打开。并且记住,禁止触发器在每个人关闭时插入,更新或从表中删除,而不仅仅是针对您的进程,所以如果必须完成,那么在数据库最不活跃的时间内(并且最好在单用户模式下)。

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

  0

好点。我之所以需要这个原因,是因为将数据从生产环境复制到测试环境时,一些AK被触发器重置,但另一个表中的相关列没有跟随。 23 9月. 082008-09-23 21:12:18


30

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

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

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上,但需要修改启用约束部分,因为原始部分没有完全工作


9

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

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

4

另一种方法是有效地禁用触发而不实际禁用它,使用被引入到触发器的附加状态变量。

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 

对于状态变量人们可以在一个表中读出某种类型的锁定控制记录的(最好的,如果限定于当前会话的上下文中),使用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 

一个潜在的主要缺点是,该触发是永久slowe d取决于访问状态变量的复杂程度。

编辑:添加一个引用这个惊人的相似2008 post by Samuel Vanga


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

2

不为批处理编程最好的答案,但对于其他人发现在搜索的快速简便的方法来暂时禁用触发这个问题,这可以在SQL Server Management Studio中完成的。

  1. 扩大桌子上的触发器文件夹
  2. 右键单击触发
  3. 禁用

enter image description here

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