17

テーブルPresentationsとがあるとしますEvents。プレゼンテーションが保存され、場所や日付などの基本的なイベント情報が含まれている場合、トリガーを使用してイベントが自動的に作成されます。(残念ながら、技術的な理由から、単にデータを 1 か所に保持してビューを使用することはできません。) さらに、プレゼンテーションの後半でこの情報を変更すると、トリガーは更新をイベントにもコピーします。そのようです:

CREATE TRIGGER update_presentations
ON Presentations
AFTER UPDATE
AS
BEGIN
    UPDATE Events
    SET Events.Date = Presentations.Date,
        Events.Location = Presentations.Location
    FROM Presentations INNER JOIN Events ON Presentations.EventID = Events.ID
    WHERE Presentations.ID IN (SELECT ID FROM inserted)
END

ここで、顧客は、ユーザーがイベントの情報を変更した場合に、プレゼンテーションにも戻るようにしたいと考えています。明らかな理由から、逆はできません。

CREATE TRIGGER update_events
ON Events
AFTER UPDATE
AS
BEGIN
    UPDATE Presentations
    SET Presentations.Date = Events.Date,
        Presentations.Location = Events.Location
    FROM Events INNER JOIN Presentations ON Events.PresentationID = Presentations.ID
    WHERE Events.ID IN (SELECT ID FROM inserted)
END

結局のところ、これにより各トリガーが次々と起動することになります。私ができることはlast_edit_by、ユーザー ID を含む列を両方のテーブルに追加することです。トリガーによって特別な無効な ID が入力された場合 (たとえば、実際の人物のすべてのユーザー ID を正にし、スクリプトのユーザー ID を負にするなど)、それを終了条件として使用できます。

    AND last_edit_by >= 0

これはうまくいくかもしれませんが、私がやりたいことは、SQL サーバーに対して、トランザクション内でトリガーが 1 回だけ起動することを示すことです。これを確認する方法はありますか?あるいは、テーブルがすでにトリガーの影響を受けていることを確認するには?


Steve Robbins のおかげで答えてください:

ネストされている可能性のあるUPDATEステートメントを、 をチェックする IF 条件でラップするだけですtrigger_nestlevel()。例えば:

CREATE TRIGGER update_presentations
ON Presentations
AFTER UPDATE
AS
BEGIN
    IF trigger_nestlevel() < 2
        UPDATE Events
        SET Events.Date = Presentations.Date,
            Events.Location = Presentations.Location
        FROM Presentations INNER JOIN Events ON Presentations.EventID = Events.ID
        WHERE Presentations.ID IN (SELECT ID FROM inserted)
END

trigger_nestlevel()0 ベースではなく、1 ベースのように見えることに注意してください。2 つのトリガーのそれぞれを 1 回だけ実行したいが、それ以上は実行したくない場合はtrigger_nestlevel() < 3、両方のトリガーをチェックします。

4

1 に答える 1

19

トランザクションごとに行うかどうかはわかりませんが、他の部分でネストされたトリガーをオンにする必要がありますか? サーバーでそれらをオフにすると、テーブルを更新する別のトリガーからトリガーは起動しません。

編集 (コメントからの回答): TRIGGER_NESTLEVELを使用するには、トリガー A を変更する必要があります。

于 2009-01-10T10:33:43.443 に答える