web-dev-qa-db-ja.com

SQL Server 2005:トリガーを一時的に無効にするT-SQL

コマンドのバッチのトリガーを無効にしてから、バッチの完了時に有効にすることは可能ですか?

トリガーをドロップして再度追加できると確信していますが、別の方法があるかどうか疑問に思っていました。

50
Austin Salonen
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

62
Matt Rogish

外部データソースから空のデータベースにデータを入力したり、データベースの問題をデバッグしたりするには、すべてのトリガーと制約を無効にする必要があります。そのためには、次のコードを使用します。

すべての制約とトリガーを無効にするには:

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 でそのソリューションを見つけましたが、元の制約が完全に機能しなかったため、有効化制約の部分を変更する必要がありました

33
kristof

ただし、これを行うことはほとんど常に悪い考えです。データベースの整合性が台無しになります。影響を考慮せず、DBAがある場合はそれを確認せずに実行しないでください。

マットのコードに従う場合は、必ずトリガーをオンに戻すことを忘れないでください。また、トリガーは、プロセスだけでなく、オフになっている間にテーブルの挿入、更新、または削除を行うすべてのユーザーに対して無効になっていることを覚えておいてください。したがって、必要な場合は、データベースが最もアクティブでない時間にシングルユーザーモードで)。

大量のデータをインポートするためにこれを行う必要がある場合、一括挿入はトリガーを起動しないことを考慮してください。ただし、一括挿入後のプロセスでは、トリガーを起動したりトリガーを起動したりすることで発生するデータ整合性の問題を修正する必要があります。

15
HLGEM

マットの答えを拡張するために、ここに [〜#〜] msdn [〜#〜] の例を示します。

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

別のアプローチは、トリガーに組み込まれている追加の状態変数を使用して、実際に無効にすることなく、トリガーを効果的に無効にすることです。

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

潜在的に大きなマイナス面は、状態変数へのアクセスの複雑さに応じて、トリガーが永続的に遅くなることです。

編集:この驚くほど似たものへの参照を追加 2008年のSamuel Vanga投稿

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

バッチプログラミングのベストアンサーではありませんが、トリガーを一時的に無効にする迅速かつ簡単な方法を探してこの質問を見つけた人にとっては、SQL Server Management Studioでこれを実現できます。

  1. テーブルのトリガーフォルダーを展開します
  2. トリガーを右クリック
  3. 無効にする

enter image description here

同じプロセスに従って再度有効にします。

2
Jeff Puckett