dedlfix: Zeichensatz-Problem

Beitrag lesen

Hi!

Du kannst in einer Tabelle, die als latin1 deklariert ist, problemlos auch Zeichen mit einer utf8-Codierung reintun, die brauchen nur ein bischen mehr Platz. Ein in latin1 codiertes 'ä' braucht 1 byte, codiere ich es in utf8, braucht es 2 byte. Das ist das ganze Geheimnis. Der Rest ist Disziplin. Klappe zu, Affe tot.

Soweit klappt das auch. (Und wenn dir nur MySQL kleiner Version 4.1 oder ein anderes DBMS ohne UTF-8-Support zur Verfügung steht, musst du so vorgehen, wenn du UTF-8-Kodiertes speichern willst.) Aber du bekommst Probleme beim Weiterverarbeiten. Eines ist, wie du schon lapidar festgestellt hast, "die brauchen nur ein bischen mehr Platz". Beispielsweise kann ein Latin1-Feld mit der Länge 10 nur 5 2-Byte-Zeichen aufnehmen. Oder wenn du einen UTF-8-kodierten 10-Zeichen-String mit einem Umlaut drin speichern willst, benötigst du 11 Byte und ein Zeichen geht verloren. Da kannst du mit Disziplin wenig dagegen ausrichten. Natürlich kannst du das Feld gleich um den Faktor drei größer anlegen (nur 3 und nicht 4, weil MySQL nur die BMP unterstüzt). Damit hast du dieses Problem erst einmal gelöst. MySQL würde es bei UTF-8-deklarierten Feldern auch nicht anders tun. Du hast nur eine falsche Anzeige, die du und andere Projektmitarbeiter richtig deuten müssen.

foo char(3) character set latin1
  bar char(1) character set utf8

Beide Felddefinitionen reservieren intern gleich viel Speicher, nämlich jeweils 3 Byte. In beide Felder kann man maximal ein UTF-8-Zeichen ablegen. Beim ersten musst du jedoch stets berücksichtigen, dass 3 eigentlich nur 1 bedeutet.

Weiterhin hast du, dass MySQL den Inhalt nach wie vor als Latin1 interpretieren wird. Abfragen wie "finde alle Einträge mit x Zeichen Länge" kann MySQL nicht richtig beantworten, weil dein ä als ä angesehen wird und bei CHARACTER_LENGTH() als 2 zählt.

Vegleiche mit Nicht-ASCII-Zeichen liefern keine sinnvollen Ergebnisse, wie sie auch für eine Sortierung benötigt werden. Es gibt ja Regeln, die bei Vergleichsvorgängen ä=a, ß=s oder auch ä=ae, ß=ss und so weiter setzen. Diese Regeln kannst du vergessen und damit die ORDER BY-Klausel.

Geht alles mit "Disziplin" zu lösen. Man frage sämtliche Daten ab und zähle deren Länge im abfragenden Programm, wenn einen die unnötige Übertragung von eigentlich gar nicht benötigten Daten nicht stört. Sortieren kann man im abfragenden Programm auch wunderbar selbst, "ORDER-BY-Klausel, ohne dich geht's auch". Die Frage ist nur, warum nimmst du diese Einbußen an Komfort und Leistung in Kauf, wenn du mit einem simplen SET NAMES all solche Probleme nicht (ständig zu berücksichtigen) hast.

Lo!