SQL Server 2008データベースのテーブルに次のトリガーがあります。繰り返し発生しているので、止める必要があります。
レコードを挿入または更新した後、そのテーブルの単一のフィールドを単純に更新しようとしています。
これがトリガーです:
ALTER TRIGGER [dbo].[tblMediaAfterInsertOrUpdate]
ON [dbo].[tblMedia]
BEFORE INSERT, UPDATE
AS
BEGIN
SET NOCOUNT ON
DECLARE @IdMedia INTEGER,
@NewSubject NVARCHAR(200)
SELECT @IdMedia = IdMedia, @NewSubject = Title
FROM INSERTED
-- Now update the unique subject field.
-- NOTE: dbo.CreateUniqueSubject is my own function.
-- It just does some string manipulation.
UPDATE tblMedia
SET UniqueTitle = dbo.CreateUniqueSubject(@NewSubject) +
CAST((IdMedia) AS VARCHAR(10))
WHERE tblMedia.IdMedia = @IdMedia
END
誰かがトリガーの挿入が別のトリガーを再び開始するのを防ぐ方法を教えてもらえますか?
これがOPの質問に関連しているかどうかはわかりませんが、トリガーで再帰または相互再帰が発生しないようにする方法を見つけるためにここに来た場合は、次のようにテストできます。
IF TRIGGER_NESTLEVEL() <= 1/*this update is not coming from some other trigger*/
MSDN リンク
私は3つの可能性を考えています。
トリガーの再帰を無効にする:
これにより、別のトリガーを呼び出すためにトリガーされたトリガーや、それ自体を再度呼び出すことが防止されます。これを行うには、次のコマンドを実行します。
_ALTER DATABASE MyDataBase SET RECURSIVE_TRIGGERS OFF
GO
_
INSTEAD OF UPDATE、INSERTのトリガーを使用
_INSTEAD OF
_トリガーを使用すると、更新/挿入される列を制御でき、コマンドを呼び出す前に置換することもできます。
IF UPDATEを使用しないようにしてトリガーを制御します
列をテストすると、トリガーがそれ自体を呼び出す場合、妥当な精度で通知されます。これを行うには、次のようにIF UPDATE()
句を使用します。
_ALTER TRIGGER [dbo].[tblMediaAfterInsertOrUpdate]
ON [dbo].[tblMedia]
FOR INSERT, UPDATE
AS
BEGIN
SET NOCOUNT ON
DECLARE @IdMedia INTEGER,
@NewSubject NVARCHAR(200)
IF UPDATE(UniqueTitle)
RETURN;
-- What is the new subject being inserted?
SELECT @IdMedia = IdMedia, @NewSubject = Title
FROM INSERTED
-- Now update the unique subject field.
-- NOTE: dbo.CreateUniqueSubject is my own function.
-- It just does some string manipulation.
UPDATE tblMedia
SET UniqueTitle = dbo.CreateUniqueSubject(@NewSubject) +
CAST((IdMedia) AS VARCHAR(10))
WHERE tblMedia.IdMedia = @IdMedia
END
_
ALTER DATABASE <dbname> SET RECURSIVE_TRIGGERS OFF
[〜#〜] on [〜#〜]AFTERトリガーの再帰的な起動が許可されます。
[〜#〜] off [〜#〜]AFTERトリガーの直接の再帰的な起動のみが許可されていません。 AFTERトリガーの間接再帰も無効にするには、sp_configureを使用して、入れ子になったトリガーサーバーオプションを0に設定します。
RECURSIVE_TRIGGERSがOFFに設定されている場合、直接再帰のみが防止されます。間接再帰を無効にするには、ネストされたトリガーのサーバーオプションを0に設定する必要もあります。
このオプションのステータスは、sys.databasesカタログビューのis_recursive_triggers_on列、またはDATABASEPROPERTYEX関数のIsRecursiveTriggersEnabledプロパティを調べることで確認できます。
私はそれを得たと思います:)
タイトルが「更新」(読み取り:挿入または更新)されたら、一意の件名を更新します。トリガーが2回目に実行されると、uniquesubjectフィールドが更新されるため、停止してトリガーから離れます。
また、変更された複数の行を処理するようにしました->これはトリガーで常に忘れます。
ALTER TRIGGER [dbo].[tblMediaAfterInsert]
ON [dbo].[tblMedia]
FOR INSERT, UPDATE
AS
BEGIN
SET NOCOUNT ON
-- If the Title is getting inserted OR updated then update the unique subject.
IF UPDATE(Title) BEGIN
-- Now update all the unique subject fields that have been inserted or updated.
UPDATE tblMedia
SET UniqueTitle = dbo.CreateUniqueSubject(b.Title) +
CAST((b.IdMedia) AS VARCHAR(10))
FROM tblMedia a
INNER JOIN INSERTED b on a.IdMedia = b.IdMedia
END
END
TRIGGER_NESTLEVEL
は特定のトリガーの再帰を防ぐために使用できますが、トリガーのオブジェクトIDを関数に渡すことが重要です。それ以外の場合は、別のトリガーによって挿入または更新が行われたときにトリガーが起動しないようにすることもできます。
IF TRIGGER_NESTLEVEL(OBJECT_ID('dbo.mytrigger')) > 1
BEGIN
PRINT 'mytrigger exiting because TRIGGER_NESTLEVEL > 1 ';
RETURN;
END;
から [〜#〜] msdn [〜#〜] :
パラメーターが指定されていない場合、TRIGGER_NESTLEVELは、呼び出しスタックのトリガーの総数を返します。これにはそれ自体が含まれます。
参照: 再帰トリガーの回避
UniqueTitleが設定されているかどうかを示す個別のNULLABLE列を持つことができます。
トリガーでtrueに設定し、「INSERTED」で値がtrueの場合、トリガーは何もしない
完全を期すために、いくつか追加します。 1回だけ実行する特定のafterトリガーがある場合は、sp_settriggerorderを使用して最後に実行するように設定できます。
また、再帰を実行しているトリガーを1つのトリガーに組み合わせるのが最善ではないかどうかも検討します。