Anschinsan: Volltextsuche - Charset Problem

Liebe Experten,

DAS PROBLEM:
in meiner MYSQL Datenbank sind türkische Texte gespeichert. Die Kollation der Tabellenfelder für Text ist 'latin_general_ci'. Diese Einstellung war das Ergebnis einiger Tests, wie die in Word-Dateien gelieferten Texte richtig angezeigt werden.

In der Word-Datei und der Datenbank steht jetzt zB ein Buchstabe Ý. Dank des <meta> tags mit charset=ISO-8859-9 wird dieser Buchstabe im Browser richtig als İ angezeigt - wenn auch im Quelltext nach wie vor Ý steht. Auch der charset war das Ergebnis einiger Experimente - ich kann nicht behaupten, dass ich weiß, was ich da tue ;(

Wenn ich nun per PHP einen String in meine SELECT Klausel für die Volltextsuche einbaue, kommt dieser String vom Formular mit dem İ. Dieser Buchstabe kommt so in der ganzen Tabelle aber kein einziges Mal vor - er ist ja immer als Ý gespeichert. Folglich findet mein Suchquery gar nix.

WOVON ICH ZU TRÄUMEN WAGE:
Gibts eine einfache Lösung, zB den Charset eines Strings zu ändern, so dass das İ im String in Ý gewandelt wird (und alle anderen Zeichen, die da irgendwie verdreht in der DB stehen).

Weiß jemand einen Link zu einer Erklärung im Stile von 'Charset für Dummies'? Alles was Google hergibt ist schon eine Spur zu hoch für mich. Ich kenne inzwischen die theoretischen Grundlagen von ISO und UTF usw. - aber ich kann das irgendwie nicht praktisch umsetzen.

Bitte helft mir - ich bin ratlos ...
Anschinsan

Nur falls da was schief geht:
İ ist ein I mit Punkt
Ý ist ein Y mit Akzent

  1. echo $begrüßung;

    [Charsets] ich kann nicht behaupten, dass ich weiß, was ich da tue ;(

    Dann müsste zuerst einmal eine Begriffserklärung erfolgen.

    Ein Charset ist eine Vorschrift, wie bestimmte Zeichen bestimmten Werten zugewiesen werden.
    Zur Verfügung stehen zum Beispiel 256 Werte (0..255, also das was ein Byte aufnehmen kann). Es gibt aber nun mehr Zeichen als 256. Meist braucht man aber nicht alle gleichzeitig, weswegen man festgelegt hat, dass die ersten 128 Werte 128 Grundzeichen (latein) beinhalten und die weiteren 128 Werte Zeichen aus bestimmten Kulturkreisen (westeuropäisch, osteuropäisch, hebräisch, ...) zugeordnet werden.

    Das Charset ISO-8859-9 legt fest, das dem Wert 221 das Zeichen İ zugewiesen ist (und umgekehrt).
    Das Charset ISO-8859-1 legt fest, das dem Wert 221 das Zeichen Ý zugewiesen ist (und umgekehrt).

    Dein Editor läuft wie hierzulande üblich sicherlich mit ISO-8859-1 (oder einem dazu (mehr oder weniger) kompatiblen Charset). Deswegen siehst du das Zeichen mit dem Wert 221 als Ý. Wenn du diesen Wert dem Browser sendest und ihm sagst, dass es ISO-8859-9 sei, dann weiß er, dass er nicht das Zeichen Ý sondern İ darstellen soll.

    in meiner MYSQL Datenbank sind türkische Texte gespeichert. Die Kollation der Tabellenfelder für Text ist 'latin_general_ci'. Diese Einstellung war das Ergebnis einiger Tests, wie die in Word-Dateien gelieferten Texte richtig angezeigt werden.

    Da ist sicher aufgrund des Unwissens so entstanden und ein ungünstiger Zustand. Wenn die DB nur für einfaches "Daten rein" und "Daten raus" verwendet wird, ist das kein Problem. Die Datenbank nimmt den Wert 221 entgegen und gibt ihn wieder aus. Sollen weitere Aufgaben der Datenbank übertragen werden, wie beispielsweise Sortieren kommt Mist raus. Jetzt muss der Wert 221 interpretiert werden und gemäß Sortiervorschrift behandelt werden. Ein Ý ist dabei sicher anders zu behandeln als ein İ. (Für die Sortierung ist übrigens der Begriff Collation zuständig.)

    Mein Vorschlag wäre, dass du erst einmal dieses Problem beseitigst. Fertige dir bitte unbedingt eine Kopie der Daten an, und experimentiere mit der Kopie, so dass bei Fehlern nicht die Originaldaten flöten gehen. Nicht alle Umwandlungen von einem Charset in ein anderes ist problemlos möglich. Wenn es zu Zeichen X aus Charset A in Charset B keinen Wert gibt, wird ein Ersatzwert genommen. Aus dem kann man das (oder besser gesagt: die verschiedenen) Ursprungszeichen nicht wiederherstellen.
    Du kannst entweder eine Kopie der Datenbank anfertigen oder nur die Tabelle kopieren. Im folgenden gehe ich von einer Tabellenkopie aus.

    Aus 'latin_general_ci' lese ich, dass du MySQL in Version 4.1 oder größer verwendest. In dieser Version wurde das Zeichenhandling stark erweitert. Zuerst solltest du dir Kapitel Character Set Support zu Gemüte führen und erkennen, an welchen Stellen überall ein Charset eingestellt/angegeben werden kann. (Default-Charset des Systems, Default-Charset einzelner Datenbanken, Default-Charset einzelner Tabellen, Charset einzelner Felder, Charset das für die Verbindung verwendet wird, ...)
    Exportiere deine Daten. Sie müssten jetzt so sein, dass Zeichen İ den Wert 221 hat. Die Datei mit den exportierten Daten kannst du nun einmal mit einem Browser öffnen. Wenn du die Zeichenkodierung (meist im Menü Ansicht zu finden) auf ISO-8859-9 stellst, solltest du den Text ordentlich lesen können. Stelle jetzt Charset und Collation für die (kopierte) Tabelle um auf 'latin5_turkish_ci'. Das müsste gemäß Handbuch ein ISO-8859-9-kompatibles Charset (mit türkischer Collation) sein. phpMyAdmin in einer aktuelle Version kann dir dabei helfen. Das kann mit verschiedenen Charsets umgehen. Möglicherweise musst du auch noch das Charset der (String-)Felder einzeln umstellen.
    Schau dir nun die Daten in der Tabelle an. Vielleicht sind sie nun schon richtig, vielleicht auch nicht. Vermutlich eher nicht. Leere nun die Tabelle und importiere die Daten. Gib dabei an, dass sie ISO-8859-9 oder latin5 sind. Nun hast du die Daten in der Tabelle und MySQL weiß auch, wie sie richtig zu interpretieren sind.

    Du könntest auch auf ein zeitgemäßeres UTF-8 umstellen, aber das zieht möglicherweise andere Probleme nach sich, da die Stringfunktionen von PHP damit nicht richtig umgehen können. UTF-8 verwendet teilweise mehrere Bytes pro Zeichen. PHP zählt aber diese Bytes einzeln. strlen() beispielsweise liefert die Anzahl der Bytes statt der Anzahl der Zeichen. Es ist zur Zeit noch nicht möglich, PHP zu sagen, dass die Strings UTF-8-kodiert sind. Wenn PHP allerdings nur stur Daten durchreicht, ist das kein Problem.

    In der Word-Datei und der Datenbank steht jetzt zB ein Buchstabe Ý. Dank des <meta> tags mit charset=ISO-8859-9 wird dieser Buchstabe im Browser richtig als İ angezeigt - wenn auch im Quelltext nach wie vor Ý steht. Auch der charset war das Ergebnis einiger Experimente -

    Das nächste Problem stellt dein Quelltext-Editor dar. Wenn der nicht auf ein Charset wie ISO-8859-9, oder allgemein gesagt: das von dir verwendete umgestellt werden kann, wird er dir immer die falschen Zeichen anzeigen, obwohl die Bytewerte stimmen.
    Vermutlich gibt es mehr Editoren, die mit UTF-8 besser umgehen können als mit dem ganzen "ISO-8859-Zoo".

    Wenn ich nun per PHP einen String in meine SELECT Klausel für die Volltextsuche einbaue, kommt dieser String vom Formular mit dem İ. Dieser Buchstabe kommt so in der ganzen Tabelle aber kein einziges Mal vor - er ist ja immer als Ý gespeichert. Folglich findet mein Suchquery gar nix.

    Die Zeichen sind weniger von Bedeutung. Es kommt wie oben erwähnt drauf an, welche Bytewerte du lieferst und wie er diese interpretiert. Bei einfachen WHERE x = y muss nichts interpretiert werden, hier werden die Bytewerte miteinander verglichen.

    WOVON ICH ZU TRÄUMEN WAGE:
    Gibts eine einfache Lösung,

    Träum weiter :-)

    zB den Charset eines Strings zu ändern, so dass das İ im String in Ý gewandelt wird (und alle anderen Zeichen, die da irgendwie verdreht in der DB stehen).

    Das ist keine Lösung. Besser ist es, zu wissen, an welcher Stelle welche Kodierung vorliegt und mit den passenden Werkzeugen, die mit dieser Kodierung umgehen können, zu arbeiten und die jeweils verwendete Kodierung dem Empfänger bekanntzugeben, damit dieser die Bytewerte richtig interpretieren kann.

    Weiterhin ist zu beachten, dass MySQL selbständig Umwandlungen vornimmt, wenn für die Verbindung ein anderes Charset angegeben ist als die Daten in der Datenbank/Tabelle/Feld stehen. SET NAMES ... als ersten Befehl der Verbindung stellt das Verbindungs-Charset um, wenn die Voreinstellung nicht dem gewünschten entspricht.

    Nur falls da was schief geht:
    İ ist ein I mit Punkt
    Ý ist ein Y mit Akzent

    Dieses Forum arbeitet mit UTF-8. Damit hat man das ISO-8859-Problem nicht, dass zwei verschiedene Zeichen den gleichen Wert erhalten. Es kann natürlich immer noch sein, dass manche Empfänger für bestimmte Zeichen keine Glyphen haben, sprich: dass Fonts für die Zeichen kein Bild enthalten. Dann gibts da ein Ersatzzeichen, meist in Form eines Kästchens.

    echo "$verabschiedung $name";