コマンドのバッチのトリガーを無効にしてから、バッチの完了時に有効にすることは可能ですか?
トリガーをドロップして再度追加できると確信していますが、別の方法があるかどうか疑問に思っていました。
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
外部データソースから空のデータベースにデータを入力したり、データベースの問題をデバッグしたりするには、すべてのトリガーと制約を無効にする必要があります。そのためには、次のコードを使用します。
すべての制約とトリガーを無効にするには:
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 でそのソリューションを見つけましたが、元の制約が完全に機能しなかったため、有効化制約の部分を変更する必要がありました
ただし、これを行うことはほとんど常に悪い考えです。データベースの整合性が台無しになります。影響を考慮せず、DBAがある場合はそれを確認せずに実行しないでください。
マットのコードに従う場合は、必ずトリガーをオンに戻すことを忘れないでください。また、トリガーは、プロセスだけでなく、オフになっている間にテーブルの挿入、更新、または削除を行うすべてのユーザーに対して無効になっていることを覚えておいてください。したがって、必要な場合は、データベースが最もアクティブでない時間にシングルユーザーモードで)。
大量のデータをインポートするためにこれを行う必要がある場合、一括挿入はトリガーを起動しないことを考慮してください。ただし、一括挿入後のプロセスでは、トリガーを起動したりトリガーを起動したりすることで発生するデータ整合性の問題を修正する必要があります。
マットの答えを拡張するために、ここに [〜#〜] 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
潜在的に大きなマイナス面は、状態変数へのアクセスの複雑さに応じて、トリガーが永続的に遅くなることです。
編集:この驚くほど似たものへの参照を追加 2008年のSamuel Vanga投稿 。
ALTER TABLE table_name DISABLE TRIGGER TRIGGER_NAME
-- Here your SQL query
ALTER TABLE table_name ENABLE TRIGGER TRIGGER_NAME