コマンドのバッチのトリガーを無効にして、バッチが完了したときに有効にすることはできますか?
トリガーを削除して再度追加できると確信していますが、別の方法があるかどうか疑問に思っていました。
コマンドのバッチのトリガーを無効にして、バッチが完了したときに有効にすることはできますか?
トリガーを削除して再度追加できると確信していますが、別の方法があるかどうか疑問に思っていました。
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 がある場合は DBA に確認せずに実行しないでください。
マットのコードに従う場合は、トリガーをオンに戻すことを忘れないでください。Aそして、プロセスだけでなく、オフになっている間、テーブルから挿入、更新、または削除するすべての人に対してトリガーが無効になっていることに注意してください。そのため、実行する必要がある場合は、データベースが最もアクティブでない時間帯に実行してくださいシングルユーザーモードで)。
大量のデータをインポートするためにこれを行う必要がある場合は、一括挿入がトリガーを起動しないことを考慮してください。ただし、一括挿入後のプロセスでは、トリガーを起動したりトリガーしたりすることによって発生したデータ整合性の問題を修正する必要があります。
マットの答えを拡張するために、 MSDNで与えられた例を次に示します。
USE AdventureWorks;
GO
DISABLE TRIGGER Person.uAddress ON Person.Address;
GO
ENABLE Trigger Person.uAddress ON Person.Address;
GO
もう 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 年の投稿への参照を追加します。