Alexander (HH): UTF8 und DBI (mysql)

Beitrag lesen

Moin Moin!

Ich hab empfange via Formular Daten in mein Perlscript (via cgi-modul).
Nun möchte ich diese Daten weiter in die DB laden (via DBI-Modul).
Soweit so gut. Jetzt hab ich mit meinem Zeichensatz "Probleme", also mit den ö, ä, ...
Ich hab gelesen, dass ich die Daten am besten utf8-kodiert in meine DB speichern soll. (Hoffe das stimmt).

Nicht unbedingt. Wenn Du nur Zeichen aus ISO-8859-1 brauchst, reicht auch ISO-8859-1. UTF-8 enthält auch alle Zeichen aus ISO-8859-1, aber eben noch ein paar Tausend mehr.

UTF-8 nur zu benutzen, weil es "gerade in Mode ist", halte ich für eine schlechte Idee.

Nun ist die Frage wie mach ich das am besten?

Nutze Perl 5.8.1 oder neuer. 5.6.x kann mit UTF-8 gar nicht umgehen (außer Du baust das Unicode-Handling komplett selbst), 5.8.0 hat ein paar üble Macken.

Bring Perl dazu, die Eingaben als UTF-8 zu behandeln; das CGI-Modul macht das leider nicht ganz automatisch, insbesondere die alten Versionen sind völlig ohne UTF-8-Unterstützung. Du wirst kaum darum herumkommen, alle Parameter mit Hilfe des Encode-Moduls von UTF-8-Bytestreams auf "echte" Unicode-Strings umzucodieren. (Bytesteam: Byte==Char, UTF-8-Zeichen belegen 1..6 Zeichen = Bytes; Unicode-String: Byte!=Char, UTF-8-Zeichen belegen exakt ein Zeichen). Siehe auch perluniintro und dort verlinkte Perl-Dokumentation; insbesondere auch utf8::is_utf8().

Die Unicode-Strings schickst Du durchs DBI-Modul in die Datenbank, je nach Datenbank ist dazu noch etwas Theater nötig. Aus der Datenbank kommen die Strings idealerweise gleich wieder als Unicode heraus, mit einem "binmode(STDOUT,':utf8')" sorgst Du dafür, dass die Unicode-Strings auch direkt nach STDOUT geschrieben werden können, ohne dass Du erneut das Encode-Modul für die Umwandlung von Unicode-Strings auf UTF-8-Bytestreams bemühen mußt.

Meine html-Seite mit Formular hat den meta-tag:
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />

Sinnlos, denn den Content-Type-Header kannst Du direkt per CGI::header() setzen, inklusive Charset. Neuere Versionen von CGI.pm schalten bei einer von vielen Schreibweisen von UTF-8 (utf8/utf-8/UTF8/UTF-8) eine rudimentäre Unicode-Unterstützung ein; siehe Source / Doku.

Oder habt ihr mir vielleicht mal ein Beispiel, wie ihr allgemein bei dem Problem perl/dbi/mysql/"Sonderzeichen" in DB schreiben, auslesen und wieder als html darstellen?

Siehe mein Unicode-Patch für DBD::ODBC 1.13, ist zwar überholt, aber durchaus noch lehrreich, insbesondere die neuen Tests in t/*.t. Im README findest Du auch einiges Know-How zu Unicode-Support verschiedener Datenbanken und DBDs.

(Und nein, bitte diesen Patch NICHT einspielen. Er ist in DBD::ODBC 1.14 und neuer komplett enthalten und funktioniert dort auch auf Nicht-Windows-Systemen!)

MySQL habe ich bislang immer vermieden, das Ding ist mir zu wenig saubere Datenbank und zu sehr eigenmächtige Müllhalde. Soweit ich mich erinnere, hast Du mit MySQL 3.x in Sachen Unicode echt schlechte Karten, 4 oder 5 sollen besser sein. Der aktuelle DBD::mysql hat ein experimentelles DB-Attribut mysql_enable_utf8, das standardmäßig false ist, analog zu DBD::Pg. Das sollte auf jeden Fall auf true gesetzt werden, bevor Du mit Unicode hantierst.

Alexander

--
Today I will gladly share my knowledge and experience, for there are no sweeter words than "I told you so".