Zeichencodierung/MySQL

Aus SELFHTML-Wiki
Wechseln zu: Navigation, Suche

Kurzanleitung für Eilige

Wichtig ist zum einen, dass die Codierung der einzelnen String-Typ-Felder (CHAR, VARCHAR, TEXT, ENUM, SET) richtig eingestellt ist. Zum anderen sollte nach jedem Verbindungsaufbau dem MySQL-Server mitgeteilt werden, welche Codierung für die zu sendenden und empfangenen Daten verwendet werden soll. Diese beiden Einstellungen sorgen auf jeden Fall für Klarheit und einen reibungslosen Datenaustausch, egal was sonst noch für Konfigurationswerte auf dem MySQL-Server eingestellt sind.

Die Codierung der Felder legen Sie beim Erstellen der Tabelle fest. Sie kann auch nachträglich geändert werden, wobei die bereits enthaltenen Daten umcodiert werden. Voraussetzung für ein reibungsloses Umcodieren ist natürlich, dass die Daten in den Felder der bisher konfigurierten Codierung entsprechen.

Beispiel
CREATE TABLE table_name ( id INT(11) NOT NULL, column_name VARCHAR(50) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL, )

Die Codierung auf der Verbindung zwischen Client und Server stellen Sie mit einer spezialisierten Funktion ein ‒ unter PHP beispielsweise mit mysql(i)_set_charset() ‒ oder mit einem „SET NAMES“-Statement.

Beachten Sie: Verwenden Sie nur SET NAMES, nicht jedoch SET CHARACTER SET!
für PHP Version ab 5.0.5 und der mysqli-Extension im objektorientierten Stil
$mysqli = new mysqli("localhost", "username", "password", "database_name"); $mysqli->set_charset("utf8");
für PHP und der mysql-Extension
$link = mysql_connect('localhost', 'username', 'password'); mysql_set_charset('utf8', $link); // diese Zeile für PHP ab Version 5.2.3 mysql_query('SET NAMES utf8', $link); // diese Zeile für PHP bis Version 5.2.3
Der Code im Beispiel beschränkt sich auf die erläuterte Funktionalität. Wenn Sie ihn übernehmen wollen, sollten Sie unbedingt auch eine Fehlerbehandlung vorsehen.
Beachten Sie, dass MySQL unter „utf8“ nur die Zeichen der BMP (Basic Multilingual Plane U+0000..U+FFFF) versteht. Um auch die Zeichen aus höheren Unicode-Regionen verwenden zu können, muss „utf8mb4“ statt „utf8“ verwendet werden, was ab MySQL-Version 5.5.3 zur Verfügung steht.

Was passiert, wenn MySQL und ein Client miteinander Daten austauschen

MySQL hat mit Version 4.1 sein Zeichencodierungskonzept stark erweitert. In der MySQL-Dokumentation beschäftigt sich das Kapitel Internationalization and Localization mit dem Thema. Doch vorab eine kleine Abschweifung.

Es gibt eine Menge Konfigurationsoptionen und -variablen [1]. Der Unterschied zwischen Option und Variable ist hier nicht weiter relevant. Einige dieser Variablen lassen sich jedenfalls individuell für die aktuelle Session (Verbindung) zwischen Client und Server umstellen. Es gibt dann neben dem globalen Wert den sessionspezifischen Wert. Man sieht das zum Beispiel im phpMyAdmin (abgekürzt PMA; ein recht beliebtes in PHP geschriebenes Verwaltungsprogramm für MySQL) unter "MySQL-System-Variablen anzeigen" / "Show MySQL system variables" auf der Startseite. Wenn keine Felder orange hinterlegt sind, kann man (ebenfalls auf der Startseite) mal den Wert "Zeichensatz / Kollation der MySQL-Verbindung" / "MySQL connection collation" umstellen. (Man macht sich dabei nichts Grundlegendes kaputt, denn das ist ein session-individueller Wert für den PMA.) Nun sollten einige Werte mit einer zweiten Zeile "(Globaler Wert)" / "(Global value)" zu sehen sein. Der obere Wert ist der session-individuelle. Nach dem Test sollte man "MySQL connection collation" wieder zurückstellen (Vergessen, was es war? utf8_general_ci passt meistens).

Für die Zeichensatz/-codierungsproblematik sind die Werte character_set_… relevant. Neben dem "Character Set" gibt es auch noch den Begriff "Collation", der oft in unmittelbarer Nähe zu "Character Set" zu finden ist. Collation hat aber zur Aufgabe Regeln für das Vergleichen von Zeichen (zum Sortieren beispielsweise) zu definieren. Für Probleme mit der Codierung kann man den Collation-Wert unberücksichtigt lassen. ‒ Übrigens, der Begriff Character Set (Zeichensatz) ist im Prinzip falsch, es müsste eigentlich Character Encoding (Zeichencodierung) heißen. Siehe dazu Zeichencodierung und geschriebene Sprache - Begrifflichkeiten.

Zurück zum eigentlichen Vorgang: Ein Client sendet ein SQL-Statement, von dem der MySQL-Server annimmt, es sei gemäß character_set_client codiert. (Innerhalb eines SQL-Statements können einzelne Werte anders codiert sein, wenn man sie besonders kennzeichnet. [2] Das braucht man im Normalfall aber nicht.) Das SQL-Statement wird umcodiert nach character_set_connection (außer den besonders gekennzeichneten Einzelwerten). Bis hier hin passiert das mit allen SQL-Statements, egal ob Daten gelesen oder geändert werden oder auch nicht. Die Ergebnisse, die in Richtung Client gesendet werden sollen, werden gemäß character_set_results codiert.

Die drei Variablen character_set_client, character_set_connection und character_set_results lassen sich mit der MySQL-C-API-Funktion mysql_set_character_set() (oder einem Pendant in einer sprachspezifischen API (PHP: mysql_set_charset()/mysqli_set_charset())) oder einem "SET NAMES"-Statement einstellen. (SET CHARACTER SET ändert die gleichen Variablen, jedoch in etwas anderer Form. In der Regel möchte man jedoch dieses Verhalten nicht.)

Soweit lässt sich das alles im Kapitel Character Set Support, speziell Connection Character Sets and Collations nachlesen. Nun fehlt aber noch der Teil wie Daten in und aus Feldern einer Tabelle geschrieben und gelesen werden. Dazu ist dem MySQL-Handbuch nicht explizit etwas zu entnehmen. Erfahrungen, gesammelt und bestätigt auch durch einige Experimente, besagen, dass die Daten noch einmal umcodiert werden, dieses Mal von character_set_connection in die Feldcodierung. Und für den Rückweg zum Client braucht es nur noch eine Umcodierung des Ergebnissets nach character_set_results.

Das waren eine Menge Umcodierungen. Idealerweise muss aber nichts umcodiert werden, wenn alle beteiligten Variablen und die Felder-Konfigurationen auf die gleiche Codierung eingestellt wurden.

Konfigurationsmöglichkeiten

Insgesamt gibt es 10 verschiedene Stellen, an denen eine Zeichencodierung konfiguriert oder angegeben werden kann. Das hört sich schlimmer an, als es am Ende ist. Einmalig während der Installation stellt man character-set-server ein. Beim Anlegen von Datenbanken sollte CHARACTER SET angegeben werden, das sich durchvererbt bis zu den Feldern. Im täglichen Betrieb benötigt man dann nur noch ein Aushandeln der Codierung nach dem Verbindungsaufbau durch einen Client.

Der nachfolgend verwendete Ausdruck „erbt von“ bedeutet, dass bei Weglassen einer Angabe der Wert von einer anderen Stelle übernommen wird.

Konfigurationsoptionen

character-set-server
Das ist der Default-Konfigurationswert für den gesamten Server.
character-set-filesystem
Dateinamen in Statements wie LOAD DATA INFILE oder SELECT … INTO OUTFILE werden gegebenenfalls nach character-set-filesystem übersetzt, bevor auf das Dateisystem zugegriffen wird.

Konfigurationsvariablen

character_set_system
In dieser Codierung werden Bezeichner (Datenbank-, Tabellen- und Feldnamen) gespeichert. Als Anwender hat man keinen Einfluss darauf, denn der Wert steht immer auf UTF-8.
character_set_database
Dieser Wert kann nicht selbst gesetzt werden. Er wird vom Server immer auf den Wert aus der Datenbank gesetzt, die man mit USE … wählt. Ist keine gewählt, entspricht er character-set-server. Verwendet wird er für character_set_connection, wenn mit SET CHARACTER SET (statt SET NAMES) die Codierung der aktuellen Client-Verbindung eingestellt werden soll.
character_set_client, character_set_connection und character_set_results
Diese drei Werte wurden bereits im vorhergehenden Abschnitt erläutert. Sie erben von character-set-server.

Weitere Stellen

Datenbank
Beim Anlegen von Datenbanken wird character-set-server als Defaultwert verwendet. Überschreiben kann man ihn mit: CREATE DATABASE … CHARACTER SET …
Tabelle
Wird von der Datenbank geerbt, wenn nicht mit CREATE TABLE tabellenname (felder-definition) CHARACTER SET … ein anderer Wert vergeben wird. Die Codierungsangabe der Tabelle hat keine weitere Aufgabe als den Default-Wert für neu anzulegende String-Felder zu stellen.
String-Felder
Wird von der Tabelle geerbt, wenn nichts anderes angegeben wurde.
Beispiel: CREATE TABLE tabellenname (feldname VARCHAR(länge) CHARACTER SET …, weitere Felder) – Bei allen Lese- und Schreibvorgängen wird der individuelle Feldwert berücksichtigt und die Daten gegebenenfalls von und in diese Codierung umkodiert.
String-Literal
Jedem String-Literal (eine in Anführungszeichen eingeschlossene Zeichenfolge) kann ein Codierungsbezeichner vorangestellt werden. Das wird man üblicherweise nicht benötigen, weil es anstrebenswert ist, nur eine einzige Codierung für alles zu verwenden. SQL-Statements und die Strings darin werden ohne weitere Angabe gemäß character_set_client interpretiert. Beispiel: SELECT _utf8'string'

Handbuch-Informationen zu den Konfigurationsoptionen