50

コマンドのバッチのトリガーを無効にして、バッチが完了したときに有効にすることはできますか?

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

4

7 に答える 7

62
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

于 2008-09-23T20:14:26.647 に答える
39

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

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

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

于 2008-09-23T21:20:24.463 に答える
16

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

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

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

于 2008-09-23T20:35:14.150 に答える
12

マットの答えを拡張するために、 MSDNで与えられた例を次に示します。

USE AdventureWorks;
GO
DISABLE TRIGGER Person.uAddress ON Person.Address;
GO
ENABLE Trigger Person.uAddress ON Person.Address;
GO
于 2013-07-04T05:38:09.050 に答える
5

もう 1 つの方法は、トリガーに組み込まれている追加の状態変数を使用して、トリガーを実際に無効にせずに効果的に無効にすることです。

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

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

編集: Samuel Vanga によるこの驚くほど類似した 2008 年の投稿への参照を追加します。

于 2013-10-02T23:53:43.213 に答える