Programmieren in MySQL Teil 6 – Trigger

In den letzten Teilen meiner Artikelserie zur Programmierung in MySQL habe ich die verschiedenen Konstrukte und typischen Anwendungsfälle der MySQL Programmierung vorgestellt. Diese Konstrukte befanden sich immer in MySQL Routinen, die per CALL aufgerufen werden mussten. Es gibt jedoch auch die Möglichkeit, MySQL-Code über Trigger automatisch aufzurufen. In diesem Artikel werde ich den Aufbau und die Anwendung von MySQL Triggern vorstellen.

Überblick über die MySQL Artikelserie

  1. Sinn und Unsinn
  2. Einrichtung und Vorbereitung
  3. Die erste Routine
  4. Grundkonstrukte
  5. Cursor
  6. Trigger
  7. Der Event Scheduler

Was sind Trigger?

Ein Trigger ist ein Auslöser, der bei einem bestimmten Ereignis Code ausführt. Im MySQL Kontext ist so ein Ereignis zum Beispiel das Löschen eines Datensatzes in eine Tabelle. Jedes Mal, wenn also per DELETE Daten gelöscht werden, wird ein bestimmter Code ausgeführt. In der Praxis werden Trigger oft genutzt, um die Konsistenz der Datenbank sicher zu stellen. Wird beispielsweise ein User gelöscht, kann man im Trigger automatisch auch alle Datensätze in anderen Tabellen löschen, die zum User gehören und damit ungültig werden.

Jeder Entwickler kennt das Problem, dass er zwar an den meisten Stellen daran gedacht hat, die abhängigen Datensätze ebenfalls zu löschen, es irgendwo aber vergessen hat. Dadurch entstehen ungültige Datensätze und die Integrität der Daten geht verloren. Der entscheidende Vorteil eines Triggers ist, dass er direkt an der Datenbank hängt. Egal, ob das DELETE in der eigenen Anwendung ausgelöst wurde, ein übermütiger Kunde im phpMyAdmin rumgespielt hat, oder die Anweisung direkt über die Konsole eingegeben wurde, der Trigger wird immer ausgelöst und stellt die Integrität der Daten sicher.

Wie erstellt man Trigger?

Die Syntax für die Erstellung eines Trigger lautet wie folgt:

CREATE TRIGGER Triggername Triggerzeitpunkt Triggerereignis ON Tabellenname FOR EACH ROW Triggeranweisungen

Den Triggernamen kann man wie einen Tabellennamen frei wählen, er muss nur eindeutig sein. Ich wähle meistens etwas wie trig_user_delete, damit man am Namen direkt erkennt, dass es ein Trigger ist und wann er ausgelöst wird.

Der Triggerzeitpunkt kann BEFORE oder AFTER sein und entscheidet darüber, ob erst die eigentliche Aktion ausgeführt wird (z.B. das DELETE) oder erst die Anweisungen des Triggers. Der Zeitpunkt hat auch Auswirkungen darauf, was im Trigger möglich ist und was nicht, mehr dazu später.

Das Triggerereignis kann DELETE, UPDATE oder INSERT sein, je nachdem bei welchem Ereignis der Trigger ausgelöst werden soll.

Die Triggeranweisungen sind die gleichen Anweisungen wie in MySQL Routinen mit ein paar Erweiterungen, aber auch Einschränkungen. Mehrere Anweisungen werden auch hier von BEGIN und END eingeschlossen.

Bei der Erstellung eines Trigger ist darauf zu achten, dass MySQL nur einen Trigger pro Zeitpunkt, Ereignis und Tabelle zulässt. Es kann also nur einen Trigger „BEFORE DELETE ON user“ geben, aber ein zusätzlicher „AFTER DELETE ON user“ oder „BEFORE DELETE ON posts“ ist erlaubt.

Trigger verwalten

Ich empfehle auch für die Verwaltung von Triggern die MySQL Workbench. Dazu klickt man mit der rechten Maustaste auf die Tabelle und wählt dann „Alter Table…“ Im sich öffnenden Fenster gibt es dann einen Reiter „Triggers“, wo man bestehende Trigger verwalten kann.

MySQL Workbench Trigger

Wer keinen direkten Zugang zur Datenbank hat, kann die Trigger auch über phpMyAdmin verwalten. Dafür geht man in die Struktur-Ansicht der Tabelle, öffnet den Link „Details…“ und sieht dann unten die bestehenden Trigger.

Trigger unter phpMyAdmin

Zusätzliche Möglichkeiten in Triggern

Neben den normalen in den letzten Teilen der Serie vorgestellten Möglichkeiten, kann man in Triggern auf die Werte des jeweiligen Datensatzes zugreifen, der gerade eingefügt, geändert oder gelöscht wird. Dafür stehen die Pseudotabellen NEW und OLD zur Verfügung. In NEW sind die Werte, die der Datensatz nach Durchführung der Aktion haben wird (bei DELETE sind diese leer), in OLD die Werte vor der Durchführung (bei INSERT sind diese leer). Möchte ist also beim Löschen eines Users in einem Forum auch seine Posts löschen, könnte ein entsprechender Trigger in etwa so aussehen:

DELIMITER $$

CREATE TRIGGER trig_user_delete
BEFORE DELETE ON user
FOR EACH ROW
BEGIN

DELETE FROM posts where user_id = OLD.id;

END$$

In OLD.id befindet sich die id des Users, der gerade gelöscht wird. Es ist wichtig, dass man bei DELETE die Pseudotabelle OLD benutzt, da der Datensatz nach der Operation ja nicht mehr existiert und NEW somit leer ist.

Es kommt aber noch besser. BEFORE Trigger werden ja vor der eigentlichen Operation ausgeführt. Daher kann man in ihnen die Werte der neuen Zeile sogar noch ändern. Hier ein einfaches Beispiel um bei der Anmeldung eines neuen Users einen Standardnamen zuzuweisen, wenn kein Name angegeben wurde:

DELIMITER $$

CREATE TRIGGER trig_user_insert
BEFORE INSERT ON user
FOR EACH ROW
BEGIN

IF NEW.user_name = '' THEN
  SET NEW.user_name = 'anomymous';
END IF;

END$$

Einschränken in Triggern

Leider gibt es in der aktuellen MySQL-Version auch einige Einschränken bei der Verwendung von Triggern. Die ärgerlichste Einschränkung ist, dass man in einem Trigger keine Änderungen an Daten der Tabelle machen kann, zu der der Trigger gehört. Möchte man also zum Beispiel in einem Forum beim Löschen eines Posts noch weitere Posts löschen, weil der gelöschte Post die Threaderöffnung war, ist dies im Trigger nicht möglich. Es bringt auch nichts, den Trigger austricksen zu wollen, indem man beispielsweise im Trigger eine Routine aufruft, die die anderen Posts löscht. MySQL merkt das und meckert. Versucht es erst gar nicht 😉

Fazit

Trigger sind eine praktische und mächtige Möglichkeit die Integrität der Daten sicherzustellen, ohne an jede Stelle denken zu müssen. Dadurch, dass sie direkt an der Datenbank dran sind, werden sie immer ausgeführt. In der Regel sind sie auch performanter, als weitere MySQL-Befehle per PHP zu schicken. Achtet beim Einsatz von Triggern jedoch darauf, sie gut zu dokumentieren. Ansonsten können sie einen zur Weißglut treiben, wenn man in einem Jahr nochmal an das Projekt dran muss und im PHP Code verzweifelt die Stelle sucht, wo die verdammten Posts gelöscht werden 😀

Merkblatt

Damit du immer schnell nachgucken kannst wie das mit der MySQL Programmierung nochmal ging, habe ich ein zweiseitiges Merkblatt erstellt. Dort stehen alle Beispiele dieser Serie nochmal drauf. Du kannst das Merkblatt ausdrucken und mit einem Blick dein Gedächtnis auffrischen.

Jetzt herunterladen

Außerdem kannst du meine regelmäßigen Entwickler Tipps bestellen. Etwa ein Mal pro Monat verschicke ich Tipps zur Arbeit als Entwickler, sowohl zur technischen Seite als auch zur Zusammenarbeit mit Kunden.

Ich bin damit einverstanden, die Tipps per E-Mail zu erhalten, kann sie aber jederzeit abbestellen. Für den Versand wird der Anbieter CleverReach benutzt. Weitere Infos in der Datenschutz-Erklärung.


 

42 thoughts on “Programmieren in MySQL Teil 6 – Trigger
  1. Der before-Trigger sind eine gute Möglichkeit, eine Versionierung des Datensatzes zu erstellen. HTTP ist ein verbindungsloses Protokoll, und wenn 2 oder mehr Benutzer zur gleichen Zeit auf einen Datensatz zugreien, gewinnt der, welcher zuletzt schreibt. Wenn man jetzt die alte Versionsnummer während des Schreibens noch mal einliest und mit der vorherigen Versionsnummer vergleicht, weiß man bei einer Abweichung, dass ein Anderer den Datensatz inzwischen verändert hat und kann im Programm entsprechend verzweigen.

    Der after-Trigger ist hervorragend dazu geeignet, jeden Datensatz an eine Sicherungstabelle anzuhängen. Damit ist es möglich, ungewollte Veränderungen nachträglich zu korrigieren.

  2. Hallo Andreas,

    danke für deine Ergänzungen. Gerade bei Anwendungen mit vielen gleichzeitigen Verbindungen kann man so sicherlich so manchem Fehler vorbeugen, den man sonst ewig suchen würde und nicht reproduziert bekommt.

    So eine Sicherungstabelle ist auch eine feine Sache, man muss nur auf die Größe der Tabelle achten.

  3. Interessanter Artikel, aber wie kann ich über einen trigger ein php script anstoßen, dass dann per exec- kommando auf einem Ubuntu ein Script anstößt, um darauf hin auf den neuen Eintrag in der Mysql zu reagieren… Nicht ganz trivial (zumindestens noch nicht für mich), da ich noch nicht mit triggern gearbeitet hatte.
    Daher auch noch mal einen Dank an Hr. Breuer bzgl. dieses interessanten Tutorials

  4. Hallo Danou,

    Das ist in der Tat nicht ganz trivial und lässt sich über einen Trigger meines Wissens nicht lösen. In Triggern kann nur SQL-Code ausgeführt werden. Um ein PHP-Script anzustoßen wäre ja eine HTTP-Abfrage nötig.

    Wie werden denn die neuen Einträge in die Datenbank eingetragen? Wenn du das Script in der Hand hast, wäre das exec-Kommando dort richtig aufgehoben. Ansonsten würde ich per Cronjob zyklisch ein PHP-Script aufrufen, welches die Datenbank auf neue Datensätze prüft.

    Was genau hast du denn vor? Vielleicht gibt es auch einen eleganteren Weg.

    Ich hoffe dass „du“ ist in Ordnung, ich halte es hier im Blog gerne persönlich.

    Schöne Grüße,
    Jonas

  5. Hallo!
    Gibt es eine Möglichkeit einen View(Abfrage) durch einen Trigger auszulösen? Wenn ja mit welchen Befehl (SHOW, OPEN, ……)?

  6. Vielen Dank für die schnelle Antwort. Mein Problem ist leider noch nicht gelöst. Ich kann die View(WelcheWohnungRaum) nicht aufrufen. Eigentlich ist es auch nicht mein Ziel, dass mir die View angezeigt wird, sondern möchte dadurch eine Art Ereigniskette ausgelösen. Hier mein SQL-Code: DROP TRIGGER IF EXISTS `testtrigger`//
    CREATE TRIGGER `testtrigger` AFTER DELETE ON `Sensordaten`
    FOR EACH ROW
    BEGIN
    SELECT *
    FROM WelcheWohnungRaum;
    END
    //
    Ich erhalte folgenden Fehler: #1415 – Not allowed to return a result set from a trigger.
    PS: Ich schreibe diese SQL-Statements gleich in das SQL Fenster in phpmyadmin. Kann man hier auch IF Anweisungen und Schleifen ausführen.

  7. Hi Chris,

    sorry, das hatte ich nicht dazu gesagt. Du kannst zwar SELECT verwenden, in Triggern aber nur mit INTO. Ansonsten versucht MySQL das Ergebnis des SELECTs zurück zu geben. So kann man beispielsweise in einer Stored Procedure ein Ergebnisset zurück liefern.

    In Triggern ist das aber nicht erlaubt, weil dieser ja nur indirekt beim Löschen, Ändern, etc. eines Datensatzes aufgerufen wird.

    Was macht denn die View bzw. warum möchtest du sie aufrufen, wenn du ihr Ergebnis gar nichts brauchst? Vielleicht kannst du die Funktionalität der View in einer Stored Procedure verlagern. Diese kannst du mit CALL im Trigger aufrufen.

    IF-Anweisungen und Schleifen kannst du nur in Routinen und Triggern verwenden. Es gibt allerdings auch eine IF-Funktion, die auch direkt im Query verwendet werden kann: http://dev.mysql.com/doc/refman/5.1/de/control-flow-functions.html

    Schöne Grüße,
    Jonas

  8. Hi!
    Ich möchte das Ergebnis speichern und eine weitere Abfrage(View) auslösen. Diese soll dann das Ergebnis wieder speichern und wieder eine andere Abfrage starten. Außerdem benötige ich nebenbei auch noch einen Timer der nach der ersten Abfrage gestartet wird. Diese Zeit die der Timer startet (also 0…30 Minuten oder 30…0 Minuten) soll dann durch ein EVENT zB. alle 10 Minuten abgefragt werden und wenn die vorgegebene Zeit vorbei ist, dann soll eine Aktion durchgeführt werden. Ich hoffe, dass ich es nicht zu kompliziert ausgetrückt habe.
    Und ich hoffe, dass es so auch realisierbar ist.

  9. Hehe, klingt wie ein Übungsprojekt um alle Elemente der MySQL-Programmierung mal auszuprobieren. Der Trigger könnte in etwa so aussehen (ungetestet):

    DROP TRIGGER IF EXISTS `testtrigger`//
    CREATE TRIGGER `testtrigger` AFTER DELETE ON `Sensordaten`
    FOR EACH ROW
    BEGIN
    #Variablen deklarieren
    DECLARE var_1, var_2 INT;
    # Timer starten
    INSERT INTO timer (starttime, endtime, finished) values (now(), now()+interval 30 minute, 0);
    # Werte aus View auslesen
    SELECT col1, col2 INTO var_1, var_2 FROM WelcheWohnungRaum;
    # Ergebnis aus View benutzen
    UPDATE table1 SET col1=var_1 WHERE col2=var_2;
    # Die letzten beiden Befehle wiederholen, um weitere Views auszulesen und die Ergebnisse zu verarbeiten
    # …

    END
    //

    Dazu dann ein Event (siehe https://www.j-breuer.de/blog/programmieren-mysql-7-event-scheduler/) welches alle 10 min. eine Stored Procedure aufruft, die etwa so aussehen könnte:

    DROP procedure IF EXISTS check_timer() //
    CREATE PROCEDURE check_timer()
    BEGIN
    DECLARE var_timer_id INT;
    # Timer fertig?
    SELECT timer_id INTO var_timer_id FROM timer WHERE endtime > now() AND finished = 0;
    IF timer_id IS NOT NULL THEN
    # reagiere auf fertigen Timer, rufe andere Routine, lösche Daten etc.
    # …
    # markiere Timer als beendet, damit er beim nächsten Aufruf nicht nochmal berücksichtigt wird
    UPDATE timer SET finished=1 WHERE timer_id = var_timer_id LIMIT 1;
    END IF;
    END//

  10. Vielen Dank für deine ausführliche Antwort. Konnte es bisher noch nicht ausprobieren. Melde mich sobald ich dies getan habe.
    mfg
    Chris

  11. Hi!
    Verstehe ich das richtig, dass ich eine Tabelle Timer erstellen muss? Wenn Ja, dann trage ich dort timer_id, Startzeit, Endzeit ein? Und wie würde diese Tabelle mit dem Trigger zusammenhängen?

  12. Ja genau, der Trigger trägt Datensätze in der Timer-Tabelle ein und die durch den Event zyklisch aufgerufene Stored Procedure überprüft, ob ein Timer abgelaufen ist.

    Mir ist gerade allerdings noch ein einfacherer Weg eingefallen, bei dem der Trigger direkt ein Event erstellt, welches nur einmalig ausgeführt wird. Der Code sähe in etwa so aus und gehört direkt in den Trigger. Eine zusätzliche Timer-Tabelle und eine Stored Procedure würdest du dann nicht mehr brauchen. Ich weiß allerdings nicht, ob es zu Problemen kommt, weil die Events dann alle gleich heißen. Das müsstest du im Zweifel nochmal ausprobieren.

    CREATE EVENT myevent
    ON SCHEDULE AT CURRENT_TIMESTAMP + INTERVAL 30 MINUTE
    DO BEGIN
    # reagiere auf fertigen Timer, rufe andere Routine, lösche Daten etc.
    # …
    END

  13. Ich habe momentan folgenden Stand und verfolge momentan deinen ersten Vorschlag. Also ich habe einen Trigger, der in die Tabelle timer einträgt, sobald ein Datensatz eingelesen wird. Weiters habe ich die Procedure erstellt, die überprüft ob der Timer abgelaufen ist. Und dazu ein Event, dass alle 10 Minuten die Procedure ausführt. Jetzt hätte ich folgende Frage. Kann man das Event so schreiben, dass es ab dem Zeitpunkt, wo der Trigger auslöst, ebenfalls auslöst. Ich stelle mir das wie folgt vor: Also der Trigger schreibt in die Tabelle und das Event löst die Procedure genau 10 Minuten nach dem der Datensatz in die Datenbank kommt das erste mal aus.

  14. Ja, das wäre dann im Prinzip mein zweiter Vorschlag. Anstatt einem zyklischen Event, welches immer wieder prüft, ob der Timer abgelaufen ist, erstellst du im Trigger ein Event, welches einmalig ausgeführt wird. Dann kannst du dir die Timer-Tabelle sparen.

  15. Hi!
    Ich verstehe nicht, warum das nicht funktioniert.
    IF Tablexyz.Test_ID = 1 THEN
    INSERT INTO abc.timer (starttime, endtime, finished) values (now(), now()+interval 24 minute, 0);
    END IF;
    Er schreibt mir immer diese Fehlermeldung; „#1109 – Unknown table ‚Tablexyz‘ in field list“ , obwohl diese Tabelle existiert. Was kann ich tun?

  16. Sorry, den Kommentar hatte ich irgendwie übersehen. Du kannst nicht einfach die Spalte einer Tabelle abfragen. MySQL weiß gar nicht, um welchen Datensatz es geht. Wenn du einen Wert mit IF überprüfen willst, solltest du ihn zunächst in einer Variable speichern, etwa so:

    DECLARE var_Test_ID INT;
    SELECT Test_ID INTO var_Test_ID FROM test_table WHERE […] LIMIT 1;
    IF Test_ID = 1 THEN
    INSERT INTO abc.timer (starttime, endtime, finished) values (now(), now()+interval 24 minute, 0);
    END IF;

  17. Ich hab ein Problem. Dieser Trigger wirft mir immer eine fehlermeldung und ich weiß nicht warum:
    CREATE TRIGGER `trig_geraete_allg_change`
    After UPDATE ON `Geraete_allgemein`
    FOR EACH ROW BEGIN
    IF `OLD.benutzer` `NEW.benutzer` THEN
    INSERT INTO `Geraete_allgemein_History`(`Geraete_id`, `Benutzer_id`,`Change_Datum`) VALUES (`NEW.ID`,`NEW.Benutzer`,NOW());
    END IF;
    END;$$

    Eigentlich sollte er funktionieren. Wo ist da der Logikfehler

  18. Hallo Asakura,

    der Fehler liegt höchstwahrscheinlich an dieser Zeile:
    IF `OLD.benutzer` `NEW.benutzer` THEN

    Da fehlt irgendwie ein Operator. Vermutlich willst du prüfen, ob sich der Benutzer geändert hat, oder? Das wäre dann:
    IF `OLD.benutzer` <> `NEW.benutzer` THEN

    Schöne Grüße,
    Jonas

  19. Danke für die Rückmeldung.
    Er hat mir beim kopieren den Operator nicht übernommen. Leider ist der Fehler auch mit Operator immer noch da 🙁 Ich weiß einfach nicht mehr weiter. Kann es an dem Old und NEW liegen, da ich diese Werte in eine andere Tabelle schreibe?

    CREATE TRIGGER `trig_geraete_allg_change`
    AFTER UPDATE ON `Geraete_allgemein`
    FOR EACH ROW
    BEGIN
    IF `OLD.benutzer` `NEW.benutzer` THEN
    INSERT INTO `Geraete_allgemein_History`(`Geraete_id`, `Benutzer_id`,`Change_Datum`) VALUES (`NEW.ID`,`NEW.Benutzer`,NOW());
    END IF;
    END;$$

    LG
    Asakura

  20. Der zeigt bei mir den Operator nicht an im Kommentar. Also bitte an diese stelle im Code den Operator dazu denken.

  21. MySQL meldet: Dokumentation
    #1064 – You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near “ at line 6

    Nur ist diese Fehlermeldung leider nicht sehr aussagekräftig. Zeile 6 wäre das insert statement.

  22. Ach so. Ja, kann sein, dass WordPress den Operator für verbotenen HTML-Code hält und filtert. Mit aussagekräftigen Fehlermeldungen ist MySQL leider immer etwas geizig.

    Versuch mal das ; in der letzten Zeile rauszunehmen. Das END dort beendet ja die gesamte Create-Anweisung und das Semikolon beendet eine Anweisung im Trigger selbst. Also letzte Zeile:
    END$$ anstatt END;$$

  23. Hallo,
    danke für deine Hilfe. Hab den Delimiter von ; in $$ ungeändert und schon klappt es. Du hast mir die Woche gerettet. Danke.

    LG
    Asa

  24. Super Seite!!!
    Ist auch für mich (Anfänger) verständlich erklärt.
    Danke für die Arbeit.

  25. Hallo Jonas,

    vielleicht kannst Du auch mir helfen?
    Ich habe eine Tabelle mit einem Feld in das kein Null rein darf. Über die Software kommen aber doch schonmal Inserts in denen dort ein Null steht.
    Ich versuche nun über den Trigger das Null in ein Leerstring umzuwandeln um die Fehlermeldung zu umgehen.
    CREATE TRIGGER avoid_empty BEFORE INSERT ON mytable
    FOR EACH ROW
    BEGIN
    IF NEW.NONS IS NULL THEN
    SET NEW.NONS = “;
    END IF;
    END;//

    Aber das scheint nicht zu funktionieren.
    Bei einem Insert mit NULL in der enstprechenden Spalte kommt wie auch ohne den Trigger: #1048 – Column ‚NONS‘ cannot be null
    Irgendeine Idee was ich falsch gemacht habe?

    Dankeschön.
    Viele Grüße
    Juliane

  26. Hi Juliane,

    von der Syntax her sieht das gut aus. Es könnte sein, dass MySQL solche Dinge zuerst checkt und dann erst den Trigger abarbeitet. Was passiert denn, wenn du mal testweise NULL erlaubst und dann einen Datensatz mit NULL einfügst? Steht dann NULL oder ein leerer String in der Datenbank? Auf diese Weise könntest du feststellen, ob es am Trigger selbst, oder an der Reihenfolge liegt.

    Schöne Grüße,
    Jonas

  27. Danke für den Hinweis.
    Die Reihenfolge scheint das Problem zu sein. Dann muss ich mir wohl was anderes einfallen lassen 🙁

    Viele Grüße
    Juliane

  28. Alles klar, dann war meine Vermutung ja richtig. Kannst du nicht NULL in der DB selbst erlauben? Durch den Trigger kann ja trotzdem nie NULL eingefügt werden. Wenn du das so machst, denkt daran den gleichen Trigger noch BEFORE UPDATE einzufügen.

    Schöne Grüße,
    Jonas

  29. Hallo Jonas,

    Ich kann (darf) die DB nicht ändern. Ist auch schwierig, da das Feld ein Primary Key ist. Die Software kann ich auch nicht ohne viel Aufwand ändern. Ich denke ich spiele jetzt ein bisschen mit Leerzeichen, die sehen an der GUI ja auch wie NULL oder “ aus 😉

    Danke für die Mühe
    Juliane

  30. … könnte ein entsprechender Trigger in etwa so aussehen:

    DELIMITER $$

    CREATE TRIGGER trig_user_delete
    BEFORE DELETE ON user
    FOR EACH ROW
    BEGIN

    DELETE FROM posts where user_id = OLD.id;

    END$$

    In OLD.id befindet sich die id des Users, der gerade gelöscht wird. Es ist wichtig, dass man bei DELETE die Pseudotabelle OLD benutzt, da der Datensatz nach der Operation ja nicht mehr existiert und NEW somit leer ist.

    Hallo,
    ich halte den letzten Satz für einen Fehler. Bevor Etwas gelöscht wird ist m.E. die ID noch vorhanden – oder sehe ich das falsch?
    Mit flottem Gruß
    Hans

  31. Hallo Hans,

    danke für die Anmerkung. Ich habe das nochmal überprüft.

    OLD und NEW bezeichnen immer die Daten vor und nach der Operation (in dem Fall dem DELETE). BEFORE und AFTER entscheiden nur darüber, ob erst gelöscht wird, oder erst der Trigger ausgeführt wird. Es ist also schon so richtig, wie es im Artikel steht. Bei DELETE muss immer OLD verwendet werden. Steht auch so um MySQL Handbuch:

    In einem INSERT-Trigger kann nur NEW.col_name benutzt werden, da keine alte Zeile vorhanden ist, und in einem DELETE-Trigger nur OLD.col_name, da keine neue Zeile vorhanden ist.
    http://dev.mysql.com/doc/refman/5.1/de/using-triggers.html

    Schöne Grüße,
    Jonas

  32. 1000-Dank für dieses super Tutorial!

    Noch eine Frag zu dem Problem „Einschränken in Triggern“, es ist also auch nicht möglich nach einem Insert in der Tabelle einen Wert in der gleichen Tabelle neu zu berechnen? Habe es versucht und wie du gesagt hast MySQl merkt alles aber was macht das für einen Sinn die Daten sind ja schon geschrieben, wenn ich AFTER INSERT auswähle…

    Liebe Grüsse
    Beni

  33. Freut mich, dass dir das Tutorial gefällt, Beni. Genau, das ist leider nicht möglich. Du könntest etwas bauen, dass der Trigger den neu berechneten Wert in eine andere Tabelle schreibt und dann regelmäßig ein Event läuft (siehe nächstes Kapitel), welches überprüft, ob in dieser Tabelle etwas steht und den neuen Wert in die eigentliche Tabelle kopiert. So richtig elegant ist das aber nicht. 😀

  34. Hi Jonas,

    Ich schreibe eine history über alle Updates in einer Tabelle in eine andere Tabelle. Diese zweite Tabelle hat aber auch trigger, die dann feuern. Das würde ich gerne verhindern. Gibt es eine Möglichkeit im trigger der 2. Tabelle zu erkennen, ob gerade ein trigger läuft?

  35. Hallo Jonas,

    vielleicht kannst du mir ja auch helfen:)

    Ich habe eine Tabelle Kunde mit Einkaufsdatum und Rückgabedatum und soll dafür einen Insert Trigger und Update Trigger erstellen, sodass Rückgabedatum nicht vor dem Einkaufsdatum liegen kann im Fehlerfall soll eine Fehlermeldung erfolgen. Meine Frage ich weiß leider nicht wie ich vorgehen soll :/

    PS: Anfänger und danke schonmal für die Rückmeldung:)

  36. Hallo Huda,

    wenn es darum geht eine Fehlermeldung an den User auszugeben, machst du diese Prüfung besser auf dem Webserver. In einem MySQL Trigger könntest du zwar entsprechend reagieren und z.B. die Änderung nicht durchführen, aber es ist recht aufwändig diesen Fehlerfall zu protokollieren, um eine Meldung an den User auszugeben.

    Viele Grüße
    Jonas

  37. Gibt es eigentlich eine Möglichkeit Prozeduren im MySQL zu debuggen bzw. bei der Ausführung zu tragen? Im MSSQL kann ich das ja über eine Funktionalität im VisualStudio aber gibt es so etwas auch für den MySQL?

Kommentieren

Deine E-Mail-Adresse wird nicht veröffentlicht. Erforderliche Felder sind mit * markiert