Rolf B: 👥 -> Fatal error: Uncaught PDOException: SQLSTATE[22007]

Beitrag lesen

Hallo Bernd,

vorab: herzlichen Dank für diese Fehlermeldung. Sie hat eine wichtige Erkenntnis hervorgebraucht. Zur Belohnung kriegst Du auch eine Lösung 😀

Ich hab jetzt mal mein Mariechen zusammen mit Tante Heidi angeworfen.

In einer Testtabelle, die ich eh noch hatte und wo ein varchar-Feld drin war, habe ich 😆 (\u1f606) eingetragen.

Erstes Ergebnis 🙄: /* #26: Access violation at address 00000000 in module 'heidisql.exe'. Read of address 00000000 Message CharCode:13 Msg:256 */

Aber das kommt bei jeder Änderung an der Tabelle. Blödes HeidiSQL. Über einen "invalid string" beschwert sie sich dagegen nicht?!

Zweites Ergebnis - INSERT mit PHP: /* SQL Fehler (1366): Incorrect string value: '\xF0\x9F\x98\x86' for column test.namen.name at row 1 */

Sehr interessant: Keine Rede vom Timestamp. Aber das war mysqli.

Jetzt mit PDO:

Fatal error: Uncaught PDOException: SQLSTATE[22007]: Invalid datetime format: 1366 Incorrect string value: '\xF0\x9F\x98\x86' for column test.namen.demo at row 1 in D:\phpweb\local_sql.php:11

Ei da isser ja! D.h. das ist ein PDO Bug (oder ein misslungenes Feature), es versucht, den SQLSTATE 22007 zu interpretieren, nehme ich an. Der Hinweis auf den Timestamp ist schlichtweg Müll, bzw. vermutlich die häufigste Ursache für diesen SQLState. Nimmt man die PDOException auseinander, steht der Timestamp-Hinweis nicht in der errorInfo. Das scheint von PDO dazugedichtet zu sein.

Wenn man im MariaDB-Handbuch nach Fehlercodes sucht, findet man SQLState 22007 zweimal. Aber das Merkwürdige ist die Kombi, die man hier findet: 22007 zusammen mit Errorcode 1366. Laut Handbuch gehören zum SQLSTATE 22007 zwei Fehlercodes:

  • 1292 - ER_TRUNCATED_WRONG_VALUE - hm.
  • 1367 - ER_ILLEGAL_VALUE_FOR_TYPE - 😀⚡💡

Was wir aber bekommen, ist

  • 1366 - ER_TRUNCATED_WRONG_VALUE_FOR_FIELD

und dazu gehört SQState HY000. Der Meldungstext passt aber zum Format bei 1366. Mir scheint, die Datenbank schickt hier den falschen SQLState. Oder schert sich nicht um ihre eigene Doku.

Aber wie nun lösen?

Recherchieren geh

Okay, PDO bringt die Meldung auch dann, wenn man DB, Table und Spalten auf utf8mb4 setzt. Aber es gibt noch was: den Connection-Zeichensatz. PDO verwendet per Default den Server Defaultzeichensatz. Und der ist ab Werk utf8mb3. Sagt das MariaDB Handbuch.

Wenn Du es darfst, konfiguriere deine Datenbank in der my.cnf (Windows: my.ini) so, dass sie utf8mb4 als Serverdefault hat (Unter MariaDB die Sektion [server], Option character_set_server). PDO folgt dem und der Fehler ist nach einem Restart des Serverdienstes weg. Bei mir zumindest!

Oder, wenn Du da nicht 'randarfst, gib im DSN ein Charset an:

$dsn = "mysql:host=...;port=...;dbname=test;charset=utf8mb4";
$user = "...";
$pass = "...";
$db = new PDO($dsn, $user, $pass);

Mann mann mann, das ist ja ein Gewürge.
Find ich...

Ich hab's mal in der Geheimabteilung des Wiki vermerkt.

Rolf

--
sumpsi - posui - obstruxi