Angenommen, Sie haben die Tabellen Presentations
und Events
. Wenn eine Präsentation gespeichert wird und grundlegende Ereignisinformationen wie Ort und Datum enthält, wird automatisch ein Ereignis mithilfe eines Triggers erstellt. (Ich fürchte, es ist aus technischen Gründen nicht möglich, die Daten einfach an einem Ort zu belassen und eine Ansicht zu verwenden.) Wenn diese Informationen später in der Präsentation geändert werden, kopiert der Auslöser die Aktualisierungen ebenfalls auf das Ereignis. etwa so:Verhindern gegenseitig rekursive Ausführung von Triggern?
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
Nun möchte der Kunde es so, dass, wenn ein Benutzer immer die Informationen im Ereignis ändert, sollte es auch auf die Präsentation zurück. Aus offensichtlichen Gründen kann ich das Gegenteil nicht tun:
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
Schließlich würde dies jeder Trigger verursachen nacheinander abzufeuern. Was ich tun könnte, ist eine Spalte last_edit_by
zu beiden Tabellen hinzufügen, die eine Benutzer-ID enthält. Wenn durch den Trigger mit einer speziellen ungültigen ID gefüllt (etwa durch alle IDs der tatsächlichen Personen Benutzer machen positiv, aber Benutzer-IDs von Skripten negativ), könnte ich das als Ausgangsbedingung verwenden:
AND last_edit_by >= 0
Dies könnte funktionieren , aber ich möchte dem SQL-Server mitteilen, dass ein Trigger innerhalb einer Transaktion nur einmal ausgelöst werden sollte. Gibt es eine Möglichkeit, dies zu überprüfen? Oder vielleicht um zu überprüfen, ob eine Tabelle bereits von einem Trigger betroffen ist?
Antwort dank Steve Robbins:
einfach die potenziell verschachtelt UPDATE
Anweisungen in einer IF-Bedingung für trigger_nestlevel()
Überprüfung wickeln. Zum Beispiel:
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
Beachten Sie, dass trigger_nestlevel()
erscheint 1-basieren, nicht 0-basiert. Wenn Sie möchten, dass jeder der beiden Trigger einmal, aber nicht öfter ausgeführt wird, suchen Sie in beiden Triggern nach trigger_nestlevel() < 3
.
Verschachtelte Trigger tatsächlich auf diese Datenbank deaktiviert zu verwenden. Mein Problem ist ein Fall von Trigger A feuernd B feuernd A, nicht feuernd A direkt. Die Einstellung verhindert dies nicht. –
Das ist rekursive Trigger, ich bin im Moment nicht an einer Maschine, aber ich bin sicher, es gibt auch verschachtelte Trigger, die Sie mit sp_config konfigurieren können. Vor ein paar Jahren war ich mit diesem Problem konfrontiert. –
Sie haben Recht; geschachtelte Trigger ist eine andere Option. Aber so, wie ich seine Dokumentation lese, würde es B daran hindern, nach A zu feuern, während ich verhindern möchte, dass A ein zweites Mal feuert. –