2017-04-05 1 views
3

まず、これまでに投稿し、SQL Server:更新トランザクションがトリガーからのものかどうかを指定するオプション?

私はテーブルが更新されるか、または行(複数可)を挿入、これ私がトリガー(AFTER INSERT, UPDATE)を作成したとき、一つの列を更新する必要があります...優しくしてください。問題は、挿入にupdate文が含まれているため、再帰的であるため、トリガを再起動することです。

私は、2つの異なるトリガにINSERTUPDATEを分離しようとしたが、他のトリガーが所定の位置にあるので、私はのためにボックスアプリケーションのデフォルト値のうち、sp_settriggerorder()trigger_nestlevel()で問題に遭遇しました。

私の質問は、更新プログラムがアプリケーション自体から来たのか、自分の引き金から来たのかを示すIF句を使用する方法はありますか?ケース、それが私の引き金であれば、私は戻ってくると簡単にELSEできて、もはや再帰的ではありません。

CREATE TRIGGER [dbo].[JobCardMetlInsertUpdateItemDesc] 
ON [dbo].[JobCardMetl] AFTER INSERT 
AS 
    BEGIN TRANSACTION [Description] 

    UPDATE JobCardMetl 
    SET JobCardMetl.Description = item.Description 
    FROM JobCardMetl 
    INNER JOIN item ON JobCardMetl.Item = item.item 
    WHERE JobCardMetl.RecordDate = (SELECT MAX(JobCardMetl.RecordDate) 
            FROM JobCardMetl) 

    COMMIT TRANSACTION [Description] 
+0

トリガー再帰(直接トリガトリガデータベースまたはサーバー(?)レベルで無効にすることができます。もちろんそれはすべてに影響します。 – RBarryYoung

答えて

3

トリガーは非常に疑わしいです:INSERTED疑似対象を参照していません。これは、INSERTの影響を受けていないレコードをトリガーしていることを意味します。常に巨大なコード臭です。

再帰的トリガーの問題の通常の解決方法は、更新される列が何であるか、つまり、 UPDATED()を使用し、自然なビジネスロジックで再帰を停止する必要があります(つまり、ガードチェックは修飾されていないため、ネストされたトリガーは更新するものは何も見つかりません)。

最終的に論理スレッジハンマー:SET CONTEXT_INFOCONTEXT_INFO()を使用することができます。あなたはそれをチェックし、それを設定し、トリガーでそれをきれいにする。既に設定されている場合、トリガーからネストされていることがわかります。清掃部分は重要です。また、セッションごとに1つのコンテキスト情報しかないので、他のapp/devが同じことをしないように祈っています(SQL 2016ではこれが改善されています)。

0

説明がまだ更新されていないかどうかを確認できます。同じ場合は、更新しないでください。そうすれば、無限の再帰を避けることができます。

また、WHEREの条件では、現在挿入されているレコードに更新を制限するように思われますが、挿入されたレコードを持つ仮想INSERTEDテーブルを使用できます。

最後に、アトミックステートメントの新しいトランザクションを開始するのは難しいようです。トリガーは、起動中のINSERTステートメントが実行されるトランザクション内で実行されることに注意してください。

ので(私はRecordDateを想定レコードを一意に識別する - 主キーです何に変更し)、次のようにあなたのトリガーを作ることができ、一緒にすべてのことを取る:

CREATE TRIGGER [dbo].[JobCardMetlInsertUpdateItemDesc] 
ON [dbo].[JobCardMetl] AFTER INSERT 
AS 
    UPDATE JobCardMetl 
    SET j.Description = item.Description 
    FROM JobCardMetl j 
    INNER JOIN item ON j.Item = item.item 
    INNER JOIN INSERTED i ON i.RecordDate = j.RecordDate 
    WHERE j.Description IS NULL OR j.Description <> item.Description 
関連する問題