テーブル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
、両方のトリガーをチェックします。