MySQL Inputvalidierung mit Triggern

Ich finds sehr praktisch, direkt auf Datenbankseite soviel wie möglich zu erledigen. Da wirds dann auch noch einen Artikel zu geben. Ich wurde neulich von Oracle inspiriert, wo folgende Konstrukte möglich sind:

create table Product (  	ProdNr integer constraint PK_Product primary key, 	ProdPreis integer constraint min_price check (ProdPreis >= 10) ); 

Damit rejected Oracle Werte kleiner als 10 für ProdPreis beim Insert / Update – super Sache und besser als das in der Application-Logik ausschließen zu müssen. Einzig doof daran ist, dass man solche Fehler sinnvoll im Programm abfangen muss und mit sprechenden Fehlermeldungen quittieren muss – sonst kanns für unbedarfte Programmierer verwirrend werden, warum denn gewisse Werte nicht in der Datenbank eingefügt werden können.

Check ist cool – aber nicht für MySQL

Zwar ist check auch in MySQL implementiert, tut aber einfach mal nichts. Als Workaround kann man für sowas Trigger verwenden, die vor Updates / Inserts automatisch aufgerufen werden und damit den gleichen Zweck erfüllen.

Sowas kann dann zum Beispiel so aussehen:

DELIMITER // 	CREATE TRIGGER min_price_four_ins  	BEFORE INSERT ON pizza  	FOR EACH ROW  	BEGIN  		DECLARE foobar INT; 		IF NEW.price < 4 THEN  			SELECT `Das ist die Fehlermeldung` INTO foobar FROM pizza; 		END IF;  	END; // DELIMITER ; 

Erstmal kryptisch und verwirrend, schauen wir uns das mal step-by-step an:

  1. Der Trigger wird vor einem Insert auf die Tabelle pizza ausgeführt.
  2. FOR EACH ROW: Der Trigger wird für jede einzufügende Zeile ausgelöst
  3. Es wird eine int-Variable angelegt und eine Fehlermeldung als String in diese Variable eingelesen. Hier wirds verwirrend. Das Konstrukt ist deswegen nötig, weil der Trigger fehlschlagen muss, um das Insert zu verhindern. Nun gibt es in MySQL kein throw exception oder fail(), also muss anderweitig ein Fehler ausgelöst werden. In diesem Fall wird also ein String in eine int-Variable eingelesen.

Schauen wir uns die Funktion des Triggers mal an:

INSERT INTO pizza (pizzaname, price) VALUES ('Salami', 3.95); 

Und – wie erwartet – wird keine Zeile eingefügt und die Fehlermeldung ausgegeben:

#1054 - Unknown column 'Das ist die Fehlermeldung' in 'field list' 

Der Trigger muss nun nochmal für Update angelegt werden und schon ist die nicht vorhandene Check-Funktionalität emuliert.

Mit Triggern lässt sich natürlich noch viel mehr machen, etwa auch andere Tabellen abfragen, Werte updaten etc. Aber Vorsicht: Es sollte irgendwo an prominenter Stelle im Programmcode selbst notiert werden, welche Trigger existieren und was sie genau für eine Funktion haben. Sonst kann sowas zu großer Verwirrung führen ;).

Wer detaillierter einsteigen möchte, sei auf das MySQL-Manual zu CREATE TRIGGER verwiesen.


Deprecated: Directive 'allow_url_include' is deprecated in Unknown on line 0