Ausführungsmodell der Trigger

Die Ausführungsmodelle der DML-Trigger? des SQL-Standards sowie von IBM mit dem DB2-Datenbanksystem und Oracle sind - wie die Syntax - weitgehend identisch, im Detail muss jedoch aufgepaßt werden.

Gemeinsamkeiten bei SQL/2003, IBM/DB2, Oracle

  • ROW-Trigger feuern einmal je manipulierten Datensatz. Wenn kein Datensatz manipuliert wird, wird auch kein ROW-TRIGGER ausgeführt.
  • STATEMENT-Trigger feuern einmal je Manipulationsbefehl. Auch wenn kein Datensatz manipuliert wird, so wird der STATEMENT-TRIGGER trotzdem genau einmal ausgeführt.
  • "Atomare Ausführung": Das feuerndes DML-Ereignis INSERT, UPDATE, DELETE? und alle direkt und indirekt gefeuerten Trigger bilden eine Ausführungseinheit. Sind alle erfolgreich ausführbar, so ist der gesamte DML-Befehl erfolgreich ausführbar. Schlägt eine Aktion fehl und bricht einer der Trigger fehlerhaft ab, so wird auch die Ausführung des feuernden Ereignisses abgebrochen. Es ist gerade dieses Verhalten, warum die Trigger so gut für die IMMEDIATE-Integritätsprüfung geeignet sind. Gleichermaßen werden alle Triggeraktionen rückgängig gemacht, wenn die ursprünglich feuerende oder eine triggerausgeführte DML-Aktion abbricht z.B. aufgrund eines fehlerhaften CONSTRAINTS.
  • kaskadierende Trigger sind möglich und üblich.
  • Das Mutating-Table-Problem tritt bei allen auf, SQL/2003 und IBM/DB2 reagieren nur anders darauf als Oracle.

Eigenheiten bei SQL/2003, IBM/DB2

  • DML-Befehle sind in den BEFORE-Triggern nicht zugelassen. Zusammen mit dem SQL/2003-Ausführungsmodell ist diese Maßnahme ausreichend um das Mutating-Table-Problem auszuschließen.
  • Triggerreihenfolge: Ein Ereignis kann mehrere Trigger feuern, dann wird die Reihenfolge mittels des Zeitpunktes der Triggererstellung (creation time) bestimmt. Je älter ein Trigger ist, umso früher wird er ausgeführt.
  • Ausführungsmodell "en detail": Tritt ein feuerndes Ereignis ein, so werden alle durch dieses Ereignis gefeuerten Trigger aktiviert. Die BEFORE-Trigger werden unabhängig davon, ob es ROW- oder STATEMENT-Trigger sind, gesammelt und "ein block" ausgeführt und die AFTER-Trigger auch, nur zu unterschiedlichen Zeitpunkten. Sind alle BEFORE-Trigger ausgeführt, dann wird die eigentliche DML-Anweisung mit all ihren betroffenen Datensätzen und Integritätsprüfungen ausgeführt. Erst im Anschluss daran, werden alle AFTER-Trigger, unabhängig von ROW- oder STATEMTENT-Triggern, ausgeführt.
  • Für kaskadierende Ereignisse und Trigger heißt dies, dass nur die BEFORE-Trigger immer jeweils unmittelbar vor dem kaskadierenden Ereignis ausgeführt werden, daher auch die Restriktion, dass die BEFORE-Trigger keine DML-Anweisungen enthalten dürfen, denn so wird das Mutating-Table-Problem ausgeschlossen und die Reihenfolgeunabhängigkeit? bleibt gewahrt. Für alle direkt oder kaskadierend gefeuerten AFTER-Trigger heißt dies, dass sie alle in dem einem AFTER-Block gesammelt werden und erst dann ausgeführt werden, wenn die jeweils feuernde DML-Anweisung vollständig ausgeführt wurde. Ihre Ausführung kann wieder kaskadierende Ereignisse und Trigger enthalten, aber für die BEFORE-Trigger gilt weiterhin die Einschränkung "keine DML-Anweisungen" mit der Konsequenz, dass kein Mutating-Table-Problem auftreten kann. Und für die AFTER-Trigger gilt, dass sie weiterhin in dem einen AFTER-Block gesammelt werden und nach dem jeweils zwischenzeitlich letzten DML-Ereignis ausgeführt werden. Somit ist insgesamt die Reihenfolgeunabhängigkeit? gewährleistet.

Eigenheiten bei Oracle:

  • DML-Befehle sind in allen Triggern zugelassen. Diese Eigenheit zusammen mit dem Oracle-Ausführungsmodell ist Ursache für das mögliche Eintreten des Mutating-Table-Problems zur Laufzeit.
  • Triggerreihenfolge: Ein Ereignis kann mehrere Trigger feuern, dann kann die Reihenfolge mittels partieller Ordnung durch die PRECEDES/FOLLOWS-Klausel gesteuert. Diese Klausel ist optional.
  • Ausführungsmodell "en detail": Tritt ein feuerndes Ereignis ein, so werden alle durch dieses Ereignis gefeuerten Trigger aktiviert. Alle BEFORE STATEMENT-Trigger für das aktuelle Ereignis werden zuerst ausgeführt. Dann werden die BEFORE ROW-Trigger für den 1. Datensatz ausgeführt, der 1. Datensatz wird manipuliert samt Integritätsprüfung und anschließend alle AFTER ROW-Trigger für diesen 1. Datensatz ausgeführt. Als nächstes werden die BEFORE ROW-Trigger des 2. Datensatzes, dann der 2. Datensatz samt Integritätsprüfung sowie anschließend seine AFTER ROW-Trigger ausgeführt. Dieser Ablauf wird nun für alle vom feuernden Ereignis betroffenen Datensätze wiederholt. Sind alle Datensätze des aktuellen Ereignisses abgearbeitet, so werden alle AFTER STATEMENT-Trigger ausgeführt. Sind mehrere Datensätze betroffen, so ist es diese unmittelbar Ausführung der ROW-Trigger zwischen aufeinander folgenden Datensätzen, zusammen mit der Freiheit, in ROW-Triggern DML-Anweisungen programmieren zu dürfen, die auch ohne kaskadierende Trigger zum Mutating-Table-Problem führt.
  • Für kaskadierende Ereignisse und Trigger heißt dies, dass die Ausführung des aktuellen Ereignisses (oberste Ebene) unterbrochen wird, an der Stelle, der auszuführenden DML-Anweisung und erst alle Trigger für dieses neue Ereignis ausgeführt werden (unteren Ebene), bis dann die noch ausstehenden Trigger der oberen Ebene ausgeführt werden. Diese Schachtelungen sind in fast beliebiger Tiefe möglich. Das Mutating-Table-Problem tritt gleichermaßen auch für kaskadierende Trigger auf.

siehe auch: TRIGGER, ECMA-Regeln, NON-DML-TRIGGER?, INSTEAD OF-Trigger

Kategorie: Aktive Datenbanken, A