Ein kleiner selbstverursachter Logikfehler bei Datenbankstrukturen macht kleinen Webanwendungen grade ein bisschen Stress. Damit Ihr damit keinen Stress habt, eine kurze Erklärung zum Thema und wie man das behebt und vermeidet.
MariaDB Update
Bis vor kurzem hatten wir auf den Servern noch die MariaDB 10.1.33 laufen, jetzt die 10.2.21 . Beim Wechsel von 10.1 auf 10.2 haben die Devs von MariaDB den globalen SQL-Modus umgestellt, daß er jetzt eher failed, statt tolerant zu sein.
Eine Beispieltabelle:
beispiel
# | Name | Typ | Kollation | Attribute | Null | Standard | Kommentare | Extra |
---|---|---|---|---|---|---|---|---|
1 | int(11) | Nein | kein(e) | AUTO_INCREMENT | ||||
2 | int(11) | Nein | 2 | |||||
3 | text | utf8_general_ci | Nein | “ | ||||
4 | int(11) | Nein | kein(e) |
Jetzt führen wir diesen Insert aus:
INSERT INTO beispiel SET id=NULL, test = 3, name=“Fritz“, counter = 0;
Klappt. Kein Fehler. Nächster Insert :
INSERT INTO beispiel SET name=“Hans“, counter = 0;
Klappt.Tabelle sieht jetzt so aus :
INSERT INTO beispiel SET id=NULL, test=9,name=“Killer“;
und schon kommt die Meldung:
ERROR 1364 (HY000): Field ‚counter‘ doesn’t have a default value
Vollkommen zurecht, weil ich im Insert der Datenbank durch Auslassung gesagt habe, nimm den Defaultwert für das ausgelassene Feld. Da es keinen Defaultwert für das Feld gibt, kann die Datenbank den auch nicht benutzen.
Jetzt ist das aber in MariaDB 10.1 noch möglich gewesen. Das lag daran, daß sich mit 10.2.4 die Defaults des Servermode geändert haben und der Modus „STRICT_TRANS_TABLES“ jetzt aktiv ist, wenn die Webanwendung das nicht selbst anders haben will. Beweis:
MariaDB [msctest]> INSERT INTO beispiel SET id=NULL, test=9,name=“Killer“;
ERROR 1364 (HY000): Field ‚counter‘ doesn’t have a default value
MariaDB [msctest]> SELECT @@SQL_MODE;
+——————————————————————————————-+
| @@SQL_MODE |
+——————————————————————————————-+
| STRICT_TRANS_TABLES,ERROR_FOR_DIVISION_BY_ZERO,NO_AUTO_CREATE_USER,NO_ENGINE_SUBSTITUTION |
+——————————————————————————————-+
1 row in set (0.00 sec)
MariaDB [msctest]> set sql_mode = „ERROR_FOR_DIVISION_BY_ZERO,NO_AUTO_CREATE_USER,NO_ENGINE_SUBSTITUTION“;
Query OK, 0 rows affected (0.00 sec)
MariaDB [msctest]> INSERT INTO beispiel SET id=NULL, test=9,name=“Killer“;
Query OK, 1 row affected, 1 warning (0.00 sec)
Jetzt die spannende Frage, mit was die Datenbank den Wert aufgefüllt hat, von dem Sie nicht weiß, wie der aussehen müßte:
id | test | name | counter |
---|---|---|---|
1 | 3 | Fritz | 0 |
2 | 2 | Hans | 0 |
5 | 9 | Killer | 0 |
Mit „0“ , was bei einem INT ja auch naheliegend ist.
Klare Ansage
Bevor jetzt jemand den MariaDB Entwicklern die Schuld dafür geben will, daß die eigene Webseite nicht mehr so funktioniert: selbst Schuld!
Ihr habt von vornherein einen Logikbug in Eurer Datenbankstruktur + Weblogik gehabt, sich darüber zu beschweren ist heuchlerisch. Da die Webanwendung sich selbst den Modus setzen kann, mit dem die Datenbank mit Ihr arbeiten soll, hätte man das ja auch mal selbst explizit so setzen können, wie man es braucht. Defaults können sich ändern, damit muß man rechnen.
Abhilfe schaffen
- Datenbankstruktur so ändern, daß ein Default vorhanden ist.
- Im Insert keine Felder auslassen, sondern explizit setzen.
- vor der Anwendung set sql_mode = „ERROR_FOR_DIVISION_BY_ZERO,NO_AUTO_CREATE_USER,NO_ENGINE_SUBSTITUTION“; absetzen, dann hat man wieder das alte Verhalten
Viel Spaß jetzt damit 🙂