dedlfix: utf8 und latin gemischt?

Beitrag lesen

Hi!

Ich habe PHP als Modul laufen.
Du meinst dies über eine .htaccess Datei realisieren?
Dann bräuchte man aber die .htaccess Datei auch in jedem Unterverzeichnis der Webanwendung oder?

Nein, eine .htaccess gilt auch für alle Unterverzeichnisse. Alternativ kannst du die Einstellungen für den VHost vornehmen, wenn du jeder Anwendung einen eigenen VHost spendiert hast.

Und: Könnte man sich dann die Zeile mit,
header("Content-Type: text/html; charset=utf-8");
sparen?

Prüf das mit einem geeignete Werkzeug, beispielsweise der livehttpheaders-Extension für den Firefox.

Ich hatte dies mit SET CHARACTER SET in einigen Beispielen gesehen.

Das sieht man gelegentlich und es klingt auf den ersten Blick ja auch zielführend, ist es aber in einigen Konstellationen nicht [*].

Was wohl noch wirklich notwendig ist (zumindest bei mir) war die Zeile mit
$DBO->query("SET collation_connection = utf8_unicode_ci");
Ohne dieser Zeile hatte ich Probleme bei einem Login mit Usernamen mit Umlauten.

Vermutlich hast du da einen Vergleich gemacht. Der ist natürlich abhängig von den Vergleichsregeln der verwendeten Kollation. Besser wäre es aber, Dinge bei denen es auf Exaktheit ankommt, wie bei Passwörtern, auf die Berücksichtigung sprachlicher Besonderheiten zu verzichten, sprich: utf8_bin für diese Felder zu verwenden. Ein Vergleich

Bei folgendem Beispiel steht die Verbindungskodierung auf UTF-8 (SET NAMES utf8 oder mysql_set_charset('utf8')) und die 'ä's sind auch UTF-8-kodiert.

CREATE TABLE `test` (  
  `utf8general` varchar(20),  
  `utf8bin` varchar(50) character set utf8 collate utf8_bin,  
  `bin` varbinary(20),  
  PRIMARY KEY  (`ID`)  
) DEFAULT CHARSET=utf8 COLLATE=utf8_general_ci;  
  
INSERT INTO `test` (`utf8general`, `utf8bin`, `bin`) VALUES ('ä', 'ä', 'ä');

Ich habe drei Spalten angelegt, eine mit utf8_general_ci, eine utf8_bin und eine rein binäre. In allen dreien ist ein 'ä' abgelegt.
Kurze Abschweifung: Der Unterschied zwischen den letzten beiden Spalten ist, dass bin sich an Bytes orientiert und utf8bin zwar UTF8-Zeichen berücksichtigt, aber Vergleiche binär durchführt.

SELECT LENGTH(bin), CHARACTER_LENGTH(bin), LENGTH(utf8bin), CHARACTER_LENGTH(utf8bin) FROM test``

Diese Abfrage liefert 2,2,2,1 als Ergebnis. LENGTH liefert generell die Byteanzahl, CHARACTER_LENGTH hingegen die Zeichenanzahl. Bei bin ist beides gleich, aber utf8bin sagt korrekt, dass 'ä' nur 1 Zeichen ist. (Bei utf8general wäre das ebenfalls so.) bin interessiert nicht weiter, weil Text und keine Binärdaten gespeichert werden sollen.

SELECT * FROM `test` WHERE `utf8general` = 'ä'  
SELECT * FROM `test` WHERE `utf8general` = 'Ä'  
SELECT * FROM `test` WHERE `utf8general` = 'a'  
SELECT * FROM `test` WHERE `utf8general` = 'A'  
  
SELECT * FROM `test` WHERE `utf8bin` = 'ä'  
SELECT * FROM `test` WHERE `utf8bin` = 'Ä'   -- leere Ergebnismenge  
SELECT * FROM `test` WHERE `utf8bin` = 'a'   -- leere Ergebnismenge  
SELECT * FROM `test` WHERE `utf8bin` = 'A'   -- leere Ergebnismenge  
  
SELECT * FROM `test` WHERE `utf8general` = 'ä' COLLATE utf8_bin  
SELECT * FROM `test` WHERE `utf8general` = 'Ä' COLLATE utf8_bin   -- leere Ergebnismenge  
SELECT * FROM `test` WHERE `utf8general` = 'a' COLLATE utf8_bin   -- leere Ergebnismenge  
SELECT * FROM `test` WHERE `utf8general` = 'A' COLLATE utf8_bin   -- leere Ergebnismenge

Diese "Messreihe" zeigt, dass entweder eine utf8_bin-Spalte oder eine explizite Angabe der gewünschten Kollation in der Query zu einem exakten Vergleich führt.

[*] Ich möchte das nicht weiter ausführen. Wer sich dafür interessiert, möge bitte die Unterschiede von SET NAMES und SET CHARACTER SET und die Arbeitsweise MySQLs bei Connection Character Sets and Collations beachten und sich ein Szenario vorstellen, bei dem eine Datenbank-Kollation (aus welchem Grunde auch immer) beispielswiese auf Latin1 steht, für die Felder und die Verbindung aber UTF8 verwendet wird.

Lo!