web-dev-qa-db-ja.com

特定の実行範囲に対してのみSQL Serverトリガーを無効にする方法はありますか?

SQL Server 2005では、トリガーがトリガーを起動する原因となっているオブジェクトを見つけるための方法はありますか?これを使用して、1つのストアドプロシージャのトリガーを無効にします。

現在のトランザクションに対してのみトリガーを無効にする他の方法はありますか?次のコードを使用することもできますが、間違っていない場合、同時トランザクションにも影響します。これは悪いことです。

DISABLE TRIGGER { [ schema_name . ] trigger_name [ ,...n ] | ALL } ON { object_name | DATABASE | ALL SERVER } [ ; ]

ENABLE TRIGGER { [ schema_name . ] trigger_name [ ,...n ] | ALL } ON { object_name | DATABASE | ALL SERVER } [ ; ]

可能な限りテーブルをできるだけ小さくしたいので、テーブルに "NoTrigger"フィールドを作成してNoTrigger = nullを実行する手法は避けたいと思います。

トリガーを回避したいのは、テーブルに手動で更新するために重要なロジックが含まれているためですが、私のストアドプロシージャがこのロジックを処理します。これは非常によく使われる手順になるので、速くしたいです。

トリガーは暗黙的なトランザクションを開始するため、サーバーに追加のオーバーヘッドを課します。トリガーが実行されるとすぐに、新しい暗黙のトランザクションが開始され、トランザクション内のすべてのデータ取得が影響を受けるテーブルのロックを保持します。

差出人: http://searchsqlserver.techtarget.com/tip/1,289483,sid87_gci1170220,00.html#trigger

36
Seibar

SQL Server Centralニュースレターで最近ハイライトされたこの記事を見たところ、接続でContext_Infoを使用すると便利な方法が提供されているようです。

http://www.mssqltips.com/tip.asp?tip=1591


テラピンによる編集:

上記のリンクには、次のコードが含まれています。

USE AdventureWorks;  
GO  
-- creating the table in AdventureWorks database  
IF OBJECT_ID('dbo.Table1') IS NOT NULL  
DROP TABLE dbo.Table1  
GO  
CREATE TABLE dbo.Table1(ID INT)  
GO   
-- Creating a trigger  
CREATE TRIGGER TR_Test ON dbo.Table1 FOR INSERT,UPDATE,DELETE  
AS  
DECLARE @Cinfo VARBINARY(128)  
SELECT @Cinfo = Context_Info()  
IF @Cinfo = 0x55555  
RETURN  
PRINT 'Trigger Executed'  
-- Actual code goes here  
-- For simplicity, I did not include any code  
GO  

トリガーが実行されないようにする場合は、次の操作を実行できます。

SET Context_Info 0x55555 
INSERT dbo.Table1 VALUES(100)
59
Cade Roux

トリガーがアプリケーションでパフォーマンスの問題を引き起こしている場合、最善のアプローチは、テーブルに対するすべての手動更新を削除し、すべての更新が正しい更新ロジックを含む挿入/更新ストアドプロシージャを通過することを要求することです。その後、トリガーを完全に削除できます。

他に何も機能しない場合は、テーブルの更新権限を拒否することをお勧めします。

これにより、コードの重複の問題も解決されます。更新SPおよびトリガーでコードを複製することは、優れたソフトウェアエンジニアリング原則の違反であり、メンテナンスの問題になります。

6

ALTER TABLE tbl DISABLE TRIGGER trg

http://doc.ddart.net/mssql/sql70/aa-az_5.htm

最初の段落の意味がわかりません

4
devio

これが良いアイデアかどうかはわかりませんが、私にはうまくいくようです。トランザクションは、トリガーが無効になっている間、他のプロセスからのテーブルへの挿入を防止する必要があります。

IF OBJECT_ID('dbo.TriggerTest') IS NOT NULL
 DROP PROCEDURE dbo.TriggerTest
GO

CREATE PROCEDURE [dbo].[TriggerTest]
AS
BEGIN TRANSACTION trnInsertTable1s
;
DISABLE TRIGGER trg_tblTable1_IU ON tblTable1
;
BEGIN -- Procedure Code
    PRINT '@@trancount'
    PRINT @@TRANCOUNT
    -- Do Stuff

END -- Procedure Code
;
ENABLE TRIGGER trg_tblTable1_IU ON tblTable1

IF @@ERROR <> 0 ROLLBACK TRANSACTION
ELSE COMMIT TRANSACTION
2
Steve

トリガーには、すべての更新(手動更新も含む)を処理するロジックが含まれていることを示しているため、ロジックが存在する場所にそれが必要です。あなたが言及した例では、ストアドプロシージャは「このロジックを処理します」とは、重複したコードを意味します。さらに、作成者に関係なくすべてのUPDATEステートメントにこのロジックが適用されていることを確認したい場合は、トリガーがその場所です。誰かがプロシージャを作成したが、ロジックをもう一度複製するのを忘れた場合はどうなりますか?ロジックを変更するときはどうなりますか?

2
Pittsburgh DBA

私はこれに少し手を加えました。一方では、質問投稿にリンクされている記事に記載されている理由に加えて、テーブルに対して実行されるコードを探す場所がもう1つあるため、私は非常に反発的です。

一方、安定した不変のビジネスルールまたはクロステーブルアクション(履歴テーブルの維持など)を適用するロジックがある場合は、これをトリガーに入れた方が安全であるため、プロシージャの作成者やプログラマは対処する必要がありません。それで-それはうまくいきます。

したがって、私の推奨事項は、必要なロジックをこの1つのprocではなくトリガーに置くことです。このprocは、必然的に、同じ免除を持ついくつかのprocに成長します。

1
Rob Allen

パフォーマンスのパフォーマンスを改善するためにトリガーを書き換えることを検討してください。

1
HLGEM

トリガーを無効にしないでください。同時トランザクションを無効にするのは正しいことです。

トリガーを無効にしたいのはなぜですか?それは何をするためのものか?なぜトリガーが問題を引き起こしているのですか?通常、データ整合性の観点からティガーを無効にすることはお勧めできません。

1
HLGEM

私は同じ問題に直面し、私のために働く次の解決策を思いつきました。

  1. 無効にするトリガーごとに1つのレコードを含む永続的なDBテーブルを作成します(例:refTriggerManager);各行にはトリガー名(例:strTriggerName = 'myTrigger')とビットフラグ(例:blnDisabled、デフォルトは0)が含まれます。

  2. トリガー本体の先頭で、refTriggerManagerでstrTriggerName = 'myTrigger'を検索します。 blnDisabled = 1の場合は、残りのトリガーコードを実行せずに戻ります。それ以外の場合は、トリガーコードを最後まで続行します。

  3. トリガーを無効にするストアドプロシージャで、次の操作を行います。


トランザクションを開始

UPDATE refTriggerManager SET blnDisabled = 1 WHERE strTriggerName = 'myTrigger'

/ *「myTrigger」を所有しているが無効にしたいテーブルを更新します。 refTriggerManager.blnDisabled = 1なので、 'myTrigger'はコードを実行せずに戻ります。 * /

UPDATE refTriggerManager SET blnDisabled = 0 WHERE triggerName = 'myTrigger'

/ *トリガーを起動するオプションの最終UPDATEコード。 refTriggerManager.blnDisabled = 0なので、 'myTrigger'は完全に実行されます。 * /

トランザクションのコミット


これらはすべてトランザクション内で行われるため、外部から隔離され、ターゲットテーブルの他のUPDATEに影響を与えません。

誰かがこのアプローチに問題を感じていますか?

ビル

0
Hoyacoder

私は他のいくつかの答えに同意します。トリガーを無効にしないでください。

これは純粋な意見ですが、私はペストのようなトリガーを避けます。データベースルールを適用するためにトリガーが使用されたケースはほとんど見つかりませんでした。私の経験には明らかなEdgeケースがあり、私はこの発言をするための私の経験しか持っていません。リレーショナルデータの挿入(ビジネスロジックから実行する必要がある)、レポートテーブルへのデータの挿入、つまりデータの非正規化(トランザクション外のプロセスで実行できる)、またはデータの変換に使用されるトリガーを通常見ました。何らかの方法で。

トリガーの正当な使用法はありますが、日常のビジネスプログラミングでは、それらの使用法はほとんどないと思います。これは現在の問題には役立たないかもしれませんが、トリガーを完全に削除して、トリガーが他の方法で実行している作業を完了することを検討できます。

0
Jason Jackson

'Exec'関数を使用して、ストアドプロシージャからのトリガーを無効または有効にできます。例:EXEC ('ENABLE TRIGGER dbo.TriggerName on dbo.TriggeredTable')

0
Nader Sghir