Hi!
ich habe eine MySQL-Datenbank, auf die ich mit phpMyAdmin zugreife. Die Einträge in die Datenbank sind mit verschiedenen Webformularen bzw, PHP-Scripts erfolgt, deren Zeichencodierung nicht einheitlich war. Ergebnis ist jedenfalls, dass die Einträge teilweise in utf8 und teilweise in iso-8859-1 codiert sind.
Du weißt aber jetzt, worauf es beim Arbeiten mit MySQL bezüglich Zeichenkodierung ankommt?
Nun möchte ich alle Einträge nach utf-8 korrigieren.
Das bedeutet am Ende, dass die betreffenden Felder (jedes einzeln!) sowohl eine mit utf8_ beginnende Kollationsangabe haben als auch deren Inhalt dieser Angabe entspricht. Das jedenfalls ist das Ziel, wenn man es mal etwas ausführlicher formuliert.
Wenn ich nun phpMyAdmin auf "German (de-utf-8)" stelle,
Abgesehen davon, dass ich jetzt nicht weiß, welche PMA-Version du verwendest und wo genau du diese Einstellung vornimmst - lass den PMA erstmal aus dem Spiel. Der macht vielleicht noch irgendwelchen Voodoo, den man nicht sehen kann (wenn man sich nicht dessen Quellen anschaut). Die Sache wird klarer, wenn du mit möglichst einfachen Mitteln erst einmal eine Bestandsanalyse machst: ein simples PHP-Script, dass sich mit dem DBMS verbindet, und mit dem du die Bytewerte der Zeichen ansehen kannst. Zudem ist noch verschiedenes Wissen notwendig.
Gundlegend solltest du wissen, was es bedeutet, wenn du beispielsweise solche Zeichenfolgen wie ü vor dir hast, die bei der Darstellung als Hexwerte ein C3BC ergeben. Möglich wäre auch C383C2BC, was dann ein besonderer Problemfall einer doppelten Kodierung wäre.
Weiterhin muss man wissen, dass MySQL bei Abfragen[*] Umkodierungen zwischen der Feldkodierung in der Verbindungskodierung vornimmt, wenn diese nicht übereinstimmen. Du siehst also nicht direkt das was im Feld steht, sondern möglicherweise einen umkodierten Wert. Deshalb ist es wichtig, im Auge zu behalten, wie die Feldkodierungen und die Verbindungskodierung gerade eingestellt sind.
[*] auch bei Inserts/Updates, aber die interessieren im Moment nicht.
Erstell dir also ein Script, dass die Verbindung aufbaut, die Zeichenkodierung der Verbindung setzt (mysql_set_charset() - zur Not SET NAMES), die Datenbank auswählt und ein einfaches SELECT-Statement auf die zu untersuchende Tabelle absetzt. Die Feldinhalte lässt du ausgeben, einmal normal und einmal durch ein urlencode() geschickt. urlencode() ist für dem Fall zwar etwas missbraucht, hat aber gegenüber bin2hex() den Vorteil, dass es "einfache" Zeichen wie a-zA-Z0-9 nicht verhext, und man sich besser auf die Sonderfälle konzentrieren kann.
Außerdem kann auch noch der Weg zwischen PHP und dem Browser für Zeichenkodierungsprobleme sorgen kann. Sorge dafür, dass der Browser ISO-8859-1 erwartet und sei dir dann bewusst, dass an ihn gesendete ISO-8859-1/Latin1-Umlaute eben wie ü zu sehen sind und UTF8-kodierte wie ü. Durch die urlencode()-Ausgabe siehst du ja, welche Bytes du wirklich sendest.
Das waren nur die Vorarbeiten zur genauen Analyse. Die weiteren Maßnahmen hängen davon ab, was diese ergibt. Eine davon könnte vielleicht die Verwendung von CONVERT(... USING ...) sein.
Wie immer bei solchen Reparaturversuchen, leg dir eine Kopie der Tabellen/Datenbank an (im PMA unter "Operationen") und arbeite mit dieser! Nicht dass du dir durch einen Fehler noch mehr zerschießt als ohnehin schon defekt ist.
Wenn du dir noch nicht sicher im Umgang mit Kodierungen bist und wie die Zeichen in der einen oder anderen als Bytewerte aussehen, mach zunächst ein paar kleine Tests. Leg mit dem PMA eine Tabelle an, schreib ein Wort mit einem Umlaut rein und schau dir an, was dein Analysescript sagt, wenn du die Verbindungskodierung auf utf8 und auf latin1 stellst.
[...] Nur habe ich dann eben alles in iso-8859-1. Aber was dann? Die ganze Datenbank exportieren, dann auf utf-8 umschalten und wieder importieren? Könnte das klappen?
Wenn der Inhalt zur Feldkodierungsangabe passt, dann reicht eine Änderung der Kodierungs-/Kollationsangabe (ALTER TABLE oder auswählen mit dem PMA), und MySQL nimmt eine Umkodierung in die neue Angabe vor. Das muss natürlich auch technisch möglich sein, denn asiatische Zeichen sind nunmal nicht in Latin1 enthalten und gingen beispielsweise bei einer Umkodierung von UTF-8 nach Latin1 verloren.
Lo!