36

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 = nullテーブルをできるだけ小さくしたいので、テーブルに「NoTrigger」フィールドを入れて、を実行する手法は避けたいと思います。

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

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

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

4

11 に答える 11

60

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

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


Terrapinによる編集:

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

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)
于 2008-10-07T12:22:26.550 に答える
7

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

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

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

于 2008-10-06T15:33:48.987 に答える
4

ALTER TABLE tbl DISABLE TRIGGER trg

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

あなたの最初の段落の意味はわかりませんが

于 2008-10-06T15:13:28.403 に答える
2

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

于 2008-10-06T15:38:09.337 に答える
2

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

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
于 2011-02-25T11:32:23.730 に答える
1

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

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

于 2008-10-06T15:17:08.163 に答える
1

パフォーマンスが問題である場合は、トリガーを書き直してパフォーマンスを改善することを検討してください。

于 2008-10-06T15:58:32.930 に答える
1

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

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

そのため、必要なロジックをこの 1 つの proc ではなく、トリガーに配置することをお勧めします。トリガーは、必然的に同じ免除で複数の proc に成長します。

于 2008-10-06T19:53:47.700 に答える
0

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

于 2012-12-10T16:12:10.557 に答える
0

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

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

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

于 2008-10-06T16:00:00.057 に答える
0

私はちょうど同じ問題に直面し、次の解決策を思いつきました。

  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 には影響しません。

このアプローチに問題がある人はいますか?

明細書

于 2010-02-05T04:02:39.040 に答える