| Trigger |
|
|
| Donnerstag, 16. Oktober 2008 um 17:41 | ||||
|
Trigger sind spezielle PL/SQL Konstrukte ähnlich den Prozeduren. Während eine Prozedur allerdings explizit durch einen anderen Block über einen Prozeduraufruf gestartet wird, wird ein Trigger automatisch ausgeführt, wenn ein “triggerndes” Ereignis eintritt. Diese Ereignisse können DML-Statements sein, aber auch DDL-Anweisungen und eine Anzahl von Systemereignissen. Hier sehen Sie die Syntax zum Erzeugen eines Triggers (eine vereinfachte Form):
Wichtig ist, daß
Hier sind einige Beispiele:
Ist das Schlüsselwort FOR EACH ROW spezifiert, ist der Trigger ein ROW-LEVEL Trigger, sonst ein Statement-Level Trigger. Bei ROW-LEVEL Triggern kann eine WHEN Bedingung formuliert werden, die in runden Klammern eingeschlossen sein muß. Die Bedingung muß erfüllt sein, damit der Trigger feuert. Diese Bedingung muß eine PL/SQL Bedingung sein, sie darf kein Subselect enthalten. Vorteil der WHEN-Klausel ist, dass der SQL-Interpreter die Bedingung prüft und, – falls diese nicht erfüllt ist -, die Kontrolle gar nicht erst an den PL/SQL-Interpreter übergibt. Folge ist ein Performancegewinn. Der trigger_body ist ein PL/SQL-Block, keine Aneinanderreihung von SQL Statements!
Um zu zeigen, wie Trigger funktionieren, nutzen wir die folgenden Tabellen:
Wir erzeugen einen Trigger, der einen Datensatz in Tabelle T5 einfügt, wenn ein Datensatz in die Tabelle T4 eingefügt wird und dabei der Wert von Spalte a <= 10 ist.
Die speziellen Variablen NEW und OLD werden benutzt, um die Werte des neuen, bzw. alten Datensatzes zu referenzieren. Bitte beachten Sie, dass im Trigger-Body den Schlüsselworten NEW und OLD ein Doppelpunkt vorangestellt werden muß. In der WHEN Bedingung des Triggers steht kein Doppelpunkt! Wir erzeugen den Trigger mit dem CREATE TRIGGER Statement, durch das Erzeugen wird der jedoch nicht auch ausgeführt. Nur ein auslösendes Ereignis, wie hier das Einfügen eines Datensatzes in T4, würde den Trigger-Body zur Ausführung bringen. Um Informationen über Trigger zu erhalten, nutzen Sie:
Um einen Trigger zu löschen:
Trigger lassen sich auch deaktivieren, ohne sie löschen zu müssen:
Bedenken Sie, dass durch das Löschen der Tabelle alle mit dieser Tabelle verbundenen Trigger mit gelöscht werden. Der Before- und After-ZeitpunktWozu genau sind nun die Zeitpunkt Before und After gedacht?? Bei ersten Versuchen scheint es völlig unerheblich, ob ein Before- oder After-Trigger genutzt wird. Z.B. findet immer ein Rollback der kompletten Anweisung statt, wenn ein Trigger mit einem Fehler terminiert. Folgendes Beispiel verhindert, dass das Gehalt eines Mitarbeiters auf mehr als 5000 geändert werden kann. (ACHTUNG, es handelt sich um einen UPDATE-Trigger, im Falle eines Inserts sind also Gehälter größer 5000 zulässig):
Obiges Beispiel ist kein gutes, denn das gleiche hätte man mit einem CHECK-Constraint erreichen können, was weitaus performanter ist, aber man sieht, dass ein Trigger die Werte eines Datensatzes nicht nur untersuchen, sondern auch ändern kann. Wie gesagt, der ROW-Trigger kann dies nur im Falle eines BEFORE-Triggers, also bevor die eigentlich DML-Anweisung ausgeführt wird. Hat man nun mehrere Trigger, die bei einer DML-Anweisung auf einer Tabelle reagieren, ist die Ausführungsreihenfolge wie folgt:
Und wozu können nun diese verschiedenen Zeitpunkte verwendet werden? Z.B. um Trigger miteinander kommunizieren zu lassen!
Ausserdem gibt es in ORACLE nicht nur Trigger, die auf DML-Ereignisse reagieren, sondern auch solche, die auf DDL- oder gar Systemereignisse (SHUTDOWN, LOGON o.ä.) reagieren. Damit werden Trigger schnell sehr mächtig, man macht sich aber das Debuggen u.U. schwer, da man über die Aktivitäten von Triggern schnell den Überblick verliert. Also setzen Sie Trigger wohlüberlegt und sparsam ein.
|
||||


Kommentare
1a-Erklärung!
Freundliche Grüsse aus der Schweiz Zitieren
ja, es gibt verschiedene Workarounds, abhängig vom gewünschten Ziel.
z.B.:
1. der Trigger nutzt das Pragma AUTONOMOUS_TRAN SACTION. Dann MUSS er allerdings am Ende des Codes committen oder rollbacken. Die Transaktion der auslösenden DML-Operation wird dadurch aber nicht beendet. Könnte also die Integrität gefährden.
2. Wenn es auf Transaktionsint egrität ankommt, könnte man Packages mit Triggern kombinieren (oder in 11g Compound Trigger verwenden). Schau mal hier, dort habe ich eine Möglichkeit beschrieben: http://www.martinbulinski.de/ORACLE/ORACLE-PLSQL/simulieren-von-on-update-cascade.html
Viele Grüße
Martin Zitieren
sie schreiben oben
< In einem Row-Level-Trigger darf nicht
< das gleiche Objekt modifiziert oder
< gelesen werden, dessen Modifikation den < Trigger ausgelöst hat.
Gibt es da einen Workarround, um es trotzdem machen zu können?
Danke und Gruß Zitieren
das kommt darauf an, was Du genau machen willst. Das "primitivste" ist sicherlich, bei der Änderung an Daten einer Tabelle mit Hilfe des Triggers in eine LOG-Tabelle zu schreiben und die irgendwann mit Deiner VB-Applikation auszulesen. Alternativ kannst Du Trigger benutzen, um in eine Pipe zu schreiben (Package DBMS_PIPE) oder ein alert auszulösen (Package DBMS_alert). Und dann gibt es nach das 10g-Feature "Database Change Notification" oder für ganz besondere Anforderungen Advanced Queueing.
Das sind meine Stichworte für Dein Problem. Schreib mal genauer, was Du machen willst, dann lohnt sich vielleicht ein kleiner Artikel zu dem Thema auf meiner Site.
Beste Grüße und frohe Ostern! Zitieren
Mich würde interesieren ob und wie ist es möglich durch den Trigger, den Client, bzw. die Applikation über DB-Ereignise zu notifizieren?
Meine VB6 Applikation greift über Oracle Client auf die DB zu.
Danke und Gruss Zitieren
Ich geb mir Mühe, in den nächsten Wochen weitere "Features" und Techniken zu beschreiben. Zitieren
Alle Kommentare dieses Beitrages als RSS-Feed.