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
然而,它几乎总是一个坏主意来做到这一点。你会混淆数据库的完整性。不要在没有考虑分支和检查dbas的情况下这样做。
如果你确实按照马特的代码,一定要记得把扳机重新打开。并且记住,禁止触发器在每个人关闭时插入,更新或从表中删除,而不仅仅是针对您的进程,所以如果必须完成,那么在数据库最不活跃的时间内(并且最好在单用户模式下)。
如果您需要这样做以导入大量数据,那么请考虑批量插入不触发触发器。但是在批量插入之后,您的过程将不得不通过触发触发器来修复引入的任何数据完整性问题。
有时从外部数据源填充空数据库或调试数据库中的问题我需要禁用所有触发器和约束。 为此我使用下面的代码:
要禁用所有约束和触发器:
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上,但需要修改启用约束部分,因为原始部分没有完全工作
为了扩展Matt的答案,下面是在MSDN上给出的一个例子。
USE AdventureWorks;
GO
DISABLE TRIGGER Person.uAddress ON Person.Address;
GO
ENABLE Trigger Person.uAddress ON Person.Address;
GO
另一种方法是有效地禁用触发而不实际禁用它,使用被引入到触发器的附加状态变量。
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。
ALTER TABLE table_name DISABLE TRIGGER TRIGGER_NAME
-- Here your SQL query
ALTER TABLE table_name ENABLE TRIGGER TRIGGER_NAME
谢谢!我认为我的SQL Server 2005 naivity在这个网站上表现得太好了。 – 2008-09-23 20:15:46
不用担心;成为DBA很长一段时间,这些东西变成自动:) – 2008-09-23 20:16:41