2008-09-23 88 views

回答

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在這個網站上表現得太好了。 – 2008-09-23 20:15:46

+0

不用擔心;成爲DBA很長一段時間,這些東西變成自動:) – 2008-09-23 20:16:41

15

然而,它幾乎總是一個壞主意來做到這一點。你會混淆數據庫的完整性。不要在沒有考慮分支和檢查dbas的情況下這樣做。

如果你確實按照馬特的代碼,一定要記得把扳機重新打開。並且記住,禁止觸發器在每個人關閉時插入,更新或從表中刪除,而不僅僅是針對您的進程,所以如果必須完成,那麼在數據庫最不活躍的時間內(並且最好在單用戶模式下)。

如果您需要這樣做以導入大量數據,那麼請考慮批量插入不觸發觸發器。但是在批量插入之後,您的過程將不得不通過觸發觸發器來修復引入的任何數據完整性問題。

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

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