Bietet Rezepte, Lösungen und ausführliche Beispiele rund um gesundes SQL und zufriedene Datenbanken.
Durch die Globalisierung werden immer häufiger die Daten UTF-8 kodiert gespeichert. Das früher häufig verwendete Latin1 wird seltener. Das Problem ist nun der "mischmasch" von Zeichensätzen. Jeder kennt wahrscheinlich das T-Shirt mit dem "Schei? Encoding" Spruch. Ein Klassiker!
Um Probleme wie diese "Warning: #1366 Incorrect string value ..." zu vermeiden, hilft (hoffentlich) folgender Encoding-Check.
* MySQL 5.1.30
Schauen wir uns die Server-System-Variablen an. Achtung, die System-Variablen existieren als SESSION und GLOBAL Version. Beide müssen geprüft werden. Beginnen wir mit dem CHARSET:
mysql> show session variables like 'char%';
+--------------------------+----------------------------------------------+
| Variable_name | Value |
+--------------------------+----------------------------------------------+
| character_set_client | latin1 |
| character_set_connection | latin1 |
| character_set_database | latin1 |
| character_set_filesystem | binary |
| character_set_results | latin1 |
| character_set_server | latin1 |
| character_set_system | utf8 |
| character_sets_dir | G:\MySQL\MySql-Server-5.1.30\share\charsets\ |
+--------------------------+----------------------------------------------+
8 rows in set (0.01 sec)
mysql> show global variables like 'char%';
+--------------------------+----------------------------------------------+
| Variable_name | Value |
+--------------------------+----------------------------------------------+
| character_set_client | latin1 |
| character_set_connection | latin1 |
| character_set_database | latin1 |
| character_set_filesystem | binary |
| character_set_results | latin1 |
| character_set_server | latin1 |
| character_set_system | utf8 |
| character_sets_dir | G:\MySQL\MySql-Server-5.1.30\share\charsets\ |
+--------------------------+----------------------------------------------+
8 rows in set (0.01 sec)
Neben dem CHARSET gibt es auch noch die Sortierung (Collation).
mysql> show session variables like 'coll%';
+----------------------+-------------------+
| Variable_name | Value |
+----------------------+-------------------+
| collation_connection | latin1_swedish_ci |
| collation_database | latin1_swedish_ci |
| collation_server | latin1_swedish_ci |
+----------------------+-------------------+
3 rows in set (0.00 sec)
mysql> show global variables like 'coll%';
+----------------------+-------------------+
| Variable_name | Value |
+----------------------+-------------------+
| collation_connection | latin1_swedish_ci |
| collation_database | latin1_swedish_ci |
| collation_server | latin1_swedish_ci |
+----------------------+-------------------+
3 rows in set (0.00 sec)
Die MySQL Konfiguration haben wir nun geprüft. Aber neben der Server-Konfiguration können auch einzelne Tabellenspalten ein spezielles Character Set zugewiesen bekommen. Wie kann dies validiert werden?
Hinter dem INFORMATION_SCHEMA verstecken sich die Metadaten der MySQL-Datenbank. Hier sind die Tabellenstrukturen und vieles mehr hinterlegt. Das schönste dabei ist, das Information_schema basiert selbst auf Tabellen, die mit SQL abgefragt werden können.
/**
* Welche CHARSET sind auf Spaltenebene definiert?
*/
SELECT character_set_name, COUNT(*) AS anzahl
FROM information_schema.columns
WHERE character_set_name IS NOT NULL
GROUP BY character_set_name;
+--------------------+--------+
| character_set_name | anzahl |
+--------------------+--------+
| latin1 | 720 |
| utf8 | 514 |
+--------------------+--------+
2 rows in set (3.83 sec)
Also bei vielen Spalten ist explizit der Charset latin1 bzw. utf8 angegeben. In welchen Tabellen und Spalten ist nun latin1 definiert?
/**
* Welcher Tabellenspalte ist explizit 'latin1' zugewiesen?
*/
SELECT table_catalog, table_schema, table_name, column_name
FROM information_schema.columns
WHERE character_set_name = 'latin1'
ORDER BY table_catalog, table_schema, table_name, column_name;
+---------------+--------------+------------------+-------------+
| table_catalog | table_schema | table_name | column_name |
+---------------+--------------+------------------+-------------+
| NULL | lager | wx1 | comment |
| NULL | lager | wx1 | link |
| NULL | lager | wx1 | node |
...
720 rows in set (0.17 sec)
In diesen Tabellen und Spalten hat sich somit noch ein "latin1" versteckt.
Ab MySQL Version 5 kann dies beispielweise so erfolgen.
mysql> ALTER TABLE wx1 CONVERT TO CHARACTER SET utf8;
Detailierte Informationen (englisch) was beim Umstellen des Zeichensatzes zu beachten ist, gibt es hier: MySQL Performance Blog