Zeichensatz

Zeichensatz

am 11.04.2008 04:44:54 von Hauke Laging

Moin,

mit Zeichensätzen stand ich ja schon immer auf Kriegsfuß, allerdings
dachte ich, dass UTF-8, konsequent an allen Fronten eingesetzt, mich
vor Unbill verschonen sollte.

Ich baue gerade eine LAMP-Anwendung und habe über phpmyadmin ein paar
Testdaten eingepflegt. Auf der Startseite lacht mich an:
MySQL-Zeichensatz: UTF-8 Unicode (utf8)

Einer meiner Testwerte ist "Schöneberg". In phpmyadmin sehe ich den
Umlaut korrekt. Wenn ich den Wert aber von PHP direkt ausgeben
lasse, dann steht da nur ein Byte in der Webseite, nämlich F6. Wie
kann das sein, wenn doch die Datenbank angeblich UTF-8 verwendet?
Die phpmyadmin-Seite ist in UTF-8 codiert. Wenn ich die speichere,
erhalte ich das "ö" als UTF-8-Folge.

Was ist da zu tun? Da PHP die Daten nur unbesehen durchreicht,
scheint mir das Problem bei MySQL zu liegen.

Was ist zu tun? Sich nicht um Zeichensätze scheren und ö in die
Datenbank schreiben, oder geht das auch eleganter? ;-)


CU

Hauke
--
http://www.hauke-laging.de/ideen/
http://zeitstempel-signatur.hauke-laging.de/
Wie können 59.054.087 Leute nur so dumm sein?

Re: Zeichensatz

am 11.04.2008 09:46:53 von unknown

Post removed (X-No-Archive: yes)

Re: Zeichensatz

am 11.04.2008 10:55:08 von Axel Schwenke

"Oliver C. Thornton" wrote:
>
>> allerdings dachte ich, dass UTF-8, konsequent an allen Fronten
>> eingesetzt, mich vor Unbill verschonen sollte.
>
> Das dachte ich auch. Aber alles konsequent auf UTF-8 zu setzen reicht
> alleine nicht aus.

Doch, das reicht aus.
Es *ist* aber eben *nicht* *alles* auf utf8 gestellt.

>> Was ist zu tun? Sich nicht um Zeichensätze scheren und ö in die
>> Datenbank schreiben, oder geht das auch eleganter? ;-)
>
> Dein PHP ist in UTF-8, dein mySQL ist in UTF-8 jetzt musst du noch
> anweisen in UTF-8 zu kommunuzieren:
> mysql_query("SET NAMES 'utf8'",$verbindung);
>
> Finde ich auch weder sinnvoll noch logisch aber ich hatte das gleiche
> problem und es half. (Der Tip kam aus dieser NG)

Das ist sogar sehr logisch. Man muß nur verstanden haben, daß der
Zeichensatz zum *Speichern* von Objekten in der Datenbank nicht
notgedrungen der gleiche sein muß wie der, den die Anwendung bei
der *Kommunikation* mit der Datenbank benutzt. Das mag bei einer
Anwendung Overkill sein, aber viele Datenbanken werden auch von
mehreren Anwendungen benutzt. Da ist es halt überaus praktisch,
wenn die Anwendungen die Daten nicht selber umwandeln müssen,
sondern MySQL einfach sagen, was sie haben wollen.

PS: utf8 ist übrigens *nicht* das kanonisch beste Encoding. Zum
einen bedeutet die Tatsache, daß ein Zeichen in utf8 1-3 Bytes
lang sein kann, einen nicht unerheblichen Mehraufwand für
praktisch alle String-Operationen. Zum anderen reserviert MySQL
*immer* 3 Byte pro utf8 Zeichen. Das kann dir bei max. Record-
Größe oder max. Index-Größe schon mal auf den Fuß fallen. Die
sind nämlich in Bytes.


XL

Re: Zeichensatz

am 11.04.2008 12:16:44 von unknown

Post removed (X-No-Archive: yes)

Re: Zeichensatz

am 11.04.2008 12:35:43 von Stefan+Usenet

On Fri, 11 Apr 2008 12:16:44 +0200 Oliver C. Thornton wrote:
> Ich habe einen englischsprachigen Mann (PHP UTF-8) und eine
> englischsprachige Frau (mySQL UTF-8), beide Tragen einen Union Jack um
> das zu verdeutlichen. Da geht man halt einfach davon aus, dass die
> auch englisch (UTF-8) miteinander reden [...]

> Wenn ich mit der DB in UTF- 8 kommuniziere könnte man annehmen, dass
> die DB per default auch mit UTF-8 antwortet. Wenn man was anderes
> haben will fände ich es latürnich logisch das extra dabei zu sagen.

Das Problem ist, dass PHP nicht wirklich weiss, welche Sprache es
spricht. Du schreibst zwar die Texte in UTF-8, aber deklariert ist
das nirgendwo, schon gar nicht im Objekt, welches die
Datenbankverbindung herstellt. Ergo weiss die Datenbank auch nicht von
alleine, was fuer eine Nationalitaet der da hat, der mit ihr reden
moechte.

Servus,
Stefan

--
http://kontaktinser.at/ - die kostenlose Kontaktboerse fuer Oesterreich

Ein starker Partner! Stefan, soviel, wie nur geht!
(Sloganizer)

Re: Zeichensatz

am 11.04.2008 13:03:25 von Hauke Laging

Oliver C. Thornton schrieb am Freitag 11 April 2008 09:46:

> Di dalam de.comp.datenbanken.mysql Hauke Laging menulis sebagai
> berikut:
>
>> mit Zeichensätzen stand ich ja schon immer auf Kriegsfuß,
>
> SIC!

Schreibt mir ein OE-User, wie süß...

Also, ich sehe in meinem Posting einen Header
Content-Type: text/plain; charset=utf-8
Content-Transfer-Encoding: 8Bit
Was darf's denn sonst noch sein?


> Dein PHP ist in UTF-8, dein mySQL ist in UTF-8 jetzt musst du noch
> anweisen in UTF-8 zu kommunuzieren:
> mysql_query("SET NAMES 'utf8'",$verbindung);

Interessant. Das hat jedenfalls das Problem gelöst. THX.


CU

Hauke
--
http://www.hauke-laging.de/ideen/
http://zeitstempel-signatur.hauke-laging.de/
Wie können 59.054.087 Leute nur so dumm sein?

Re: Zeichensatz

am 11.04.2008 13:09:09 von Hauke Laging

Axel Schwenke schrieb am Freitag 11 April 2008 10:55:

> PS: utf8 ist übrigens *nicht* das kanonisch beste Encoding.

Sondern was?


> Zum
> einen bedeutet die Tatsache, daß ein Zeichen in utf8 1-3 Bytes
> lang sein kann,

"UTF-8 unterstützt bis zu vier Byte,"
http://de.wikipedia.org/wiki/UTF_8

Die "3 pro Zeichen"-Regel ist wohl ein Statistikding.


> einen nicht unerheblichen Mehraufwand für
> praktisch alle String-Operationen. Zum anderen reserviert MySQL
> *immer* 3 Byte pro utf8 Zeichen. Das kann dir bei max. Record-
> Größe oder max. Index-Größe schon mal auf den Fuß fallen. Die
> sind nämlich in Bytes.

Wegen einer kleinen Index-Auseinandersetzung habe ich zufällig
gestern gerade die Doku dazu gelesen und weiß deshalb, dass bei
Strings die Angabe der Indexlänge Zeichen meint und nur bei
Binärdaten Bytes. Und da erscheint es mir total abwegig, wenn das
ausgerechnet bei der Recordlänge anders sein sollte,
zumal "reserviert MySQL *immer* 3 Byte pro utf8 Zeichen" dann ja
eine völlig sinnfreie Aussage wäre (es sei denn, Du meinst mit
Recordlänge irgendwas anderes als ich).


CU

Hauke
--
http://www.hauke-laging.de/ideen/
http://zeitstempel-signatur.hauke-laging.de/
Wie können 59.054.087 Leute nur so dumm sein?

Re: Zeichensatz

am 11.04.2008 14:50:42 von Claus Reibenstein

Axel Schwenke schrieb:

> PS: utf8 ist übrigens *nicht* das kanonisch beste Encoding. Zum
> einen bedeutet die Tatsache, daß ein Zeichen in utf8 1-3 Bytes
> lang sein kann, einen nicht unerheblichen Mehraufwand für
> praktisch alle String-Operationen.

Bis hierhin richtig.

> Zum anderen reserviert MySQL
> *immer* 3 Byte pro utf8 Zeichen.

Das wäre mir neu. Kannst Du diese kühne Behauptung irgendwie belegen?

Der Vorteil von UTF-8 ist ja gerade, dass eben _nicht_ immer die volle
Bytelänge pro Zeichen benötigt wird. Es wäre ziemlich krank, wenn MySQL
diesen Vorteil nicht nutzen würde.

Gruß. Claus

Re: Zeichensatz

am 11.04.2008 15:16:00 von unknown

Post removed (X-No-Archive: yes)

Re: Zeichensatz

am 11.04.2008 15:57:35 von mueller

Oliver C. Thornton wrote:
> Di dalam de.comp.datenbanken.mysql Stefan Froehlich menulis sebagai
> berikut:
>> Das Problem ist, dass PHP nicht wirklich weiss, welche Sprache es
>> spricht. Du schreibst zwar die Texte in UTF-8, aber deklariert ist
>> das nirgendwo, schon gar nicht im Objekt, welches die
>> Datenbankverbindung herstellt. Ergo weiss die Datenbank auch nicht
>> von alleine, was fuer eine Nationalitaet der da hat, der mit ihr
>> reden moechte.
>
> Auch da wäre meine Reaktion wie folgt: Jemand spricht mich irgendwie an,
> ich antworte auf Englisch oder Deutsch, eben meine Default-Spache, es
> sei denn ich erkenne die andere SPrache und kann entsprechend antworten.
> Ansonsten würde ich halt default-kommunikation betreiben: Englisch/UTF-8
> eben das was ich hab.
>

Wie willst Du bei einem 'SELECT foo FROM bar' erkennen, das PHP die Antwort
gerne als utf-8 hätte? Oder doch lieber in Iso8859-15?

Schönen Freitag noch
Robert

Re: Zeichensatz

am 11.04.2008 16:30:52 von Christian Kirsch

Claus Reibenstein schrieb:
> Axel Schwenke schrieb:

>> Zum anderen reserviert MySQL
>> *immer* 3 Byte pro utf8 Zeichen.
>
> Das wäre mir neu. Kannst Du diese kühne Behauptung irgendwie belegen?
>
> Der Vorteil von UTF-8 ist ja gerade, dass eben _nicht_ immer die volle
> Bytelänge pro Zeichen benötigt wird. Es wäre ziemlich krank, wenn MySQL
> diesen Vorteil nicht nutzen würde.
>

Naja, feste Recordlänge halt... Ob es kränker ist, sich mit
unterschiedlich langen oder mit überlangen Records rumzuschschlagen,
könnte sicherlich debattiert werden.

Aus der Dokumentation (ist ja immer gut, das mal reinzugucken)

> RFC 3629 describes encoding sequences that take from one to four bytes. Currently, MySQL UTF8 support does not include four-byte sequences. (An older standard for UTF8 encoding is given by RFC 2279, which describes UTF8 sequences that take from one to six bytes. RFC 3629 renders RFC 2279 obsolete; for this reason, sequences with five and six bytes are no longer used.)
>
> Tip: To save space with UTF8, use VARCHAR instead of CHAR. Otherwise, MySQL has to reserve 30 bytes for a CHAR(10) CHARACTER SET utf8 column, because that's the maximum possible length.

MaW: Wenn Du CHAR() als Datentyp benutzt, verwendet MySQL bei
UTF-8-Feldern dreimal soviel Platz wie bei Latin[1-15]-Feldern.

Re: Zeichensatz

am 11.04.2008 16:38:21 von unknown

Post removed (X-No-Archive: yes)

Re: Zeichensatz

am 11.04.2008 18:26:55 von Axel Schwenke

Hauke Laging <2q2008@hauke-laging.de> wrote:
> Axel Schwenke schrieb am Freitag 11 April 2008 10:55:
>
>> PS: utf8 ist übrigens *nicht* das kanonisch beste Encoding.
>
> Sondern was?

Es gibt keins. Aber wenn die Daten in einem 8-bit Encoding darstellbar
sind, dann wäre das ein heißer Kandidat. An der Schnittstelle kann
MySQL ja trotzdem noch utf8 sprechen.

>> Zum
>> einen bedeutet die Tatsache, daß ein Zeichen in utf8 1-3 Bytes
>> lang sein kann,
>
> "UTF-8 unterstützt bis zu vier Byte,"
> http://de.wikipedia.org/wiki/UTF_8
>
> Die "3 pro Zeichen"-Regel ist wohl ein Statistikding.

Ist es nicht. Aber MySQL unterstützt nur die BMP
http://de.wikipedia.org/wiki/Unicode#.C3.9Cberblick_.C3.BCbe r_die_Ebenen

Und für die 2^16 Code Points der BMP reichen in utf8 3 Bytes.

>> einen nicht unerheblichen Mehraufwand für
>> praktisch alle String-Operationen. Zum anderen reserviert MySQL
>> *immer* 3 Byte pro utf8 Zeichen. Das kann dir bei max. Record-
>> Größe oder max. Index-Größe schon mal auf den Fuß fallen. Die
>> sind nämlich in Bytes.
>
> Wegen einer kleinen Index-Auseinandersetzung habe ich zufällig
> gestern gerade die Doku dazu gelesen und weiß deshalb, dass bei
> Strings die Angabe der Indexlänge Zeichen meint und nur bei
> Binärdaten Bytes. Und da erscheint es mir total abwegig, wenn das
> ausgerechnet bei der Recordlänge anders sein sollte,
> zumal "reserviert MySQL *immer* 3 Byte pro utf8 Zeichen" dann ja
> eine völlig sinnfreie Aussage wäre (es sei denn, Du meinst mit
> Recordlänge irgendwas anderes als ich).

Du mußt mir nicht glauben, ich habe auch so recht :)

Aber du kannst es ausprobieren:

CREATE TABLE t1 (c1 VARCHAR(15000), c2 VARCHAR(15000)) CHARSET utf8;

geht in die Hose, klappt aber mit latin1. Mit Indexen ähnlich.


XL

Re: Zeichensatz

am 11.04.2008 18:50:20 von Claus Reibenstein

Christian Kirsch schrieb:

> Claus Reibenstein schrieb:
>
>> Axel Schwenke schrieb:
>
>>> Zum anderen reserviert MySQL
>>> *immer* 3 Byte pro utf8 Zeichen.
>>
>> Das wäre mir neu. Kannst Du diese kühne Behauptung irgendwie belegen?
>>
>> Der Vorteil von UTF-8 ist ja gerade, dass eben _nicht_ immer die volle
>> Bytelänge pro Zeichen benötigt wird. Es wäre ziemlich krank, wenn MySQL
>> diesen Vorteil nicht nutzen würde.
>
> Naja, feste Recordlänge halt...

Davon war bislang nirgends die Rede.

> Aus der Dokumentation (ist ja immer gut, das mal reinzugucken)
>
>> RFC 3629 [...]

Hierfür irrelevant.

>> Tip: To save space with UTF8, use VARCHAR instead of CHAR. [...]

Ein deutlicher Hinweis darauf, dass bei VARCHAR _keine_ feste
Zeichenbreite von 3 Bytes verwendet wird, womit Axels Behauptung
widerlegt wäre.

Gruß. Claus

Re: Zeichensatz

am 11.04.2008 18:51:30 von Axel Schwenke

"Oliver C. Thornton" wrote:
> Di dalam de.comp.datenbanken.mysql Axel Schwenke menulis sebagai
> berikut:
>
>> > Das dachte ich auch. Aber alles konsequent auf UTF-8 zu setzen
>> > reicht alleine nicht aus.
>>
>> Doch, das reicht aus.
>> Es *ist* aber eben *nicht* *alles* auf utf8 gestellt.
>
> Es ist ein rein gedankliches Konstrukt welches man ohne besondere
> Kenntnis der Materie ansich einfach annimmt.
> Ich habe einen englischsprachigen Mann (PHP UTF-8) und eine
> englischsprachige Frau (mySQL UTF-8), beide Tragen einen Union Jack um
> das zu verdeutlichen. Da geht man halt einfach davon aus, dass die auch
> englisch (UTF-8) miteinander reden anstatt Latein oder Kyrillisch ohne
> das erst sonderlich vereinbaren zu müssen. Also ich zumindest, der OP
> wahrscheinlich auch.

Dein Vergleich hinkt. PHP sagt MySQL ja gerade nicht, welchen Dialekt
es spricht. MySQL nimmt dann einfach an, es wäre latin1.

>> Das ist sogar sehr logisch. Man muß nur verstanden haben, daß der
>> Zeichensatz zum *Speichern* von Objekten in der Datenbank nicht
>> notgedrungen der gleiche sein muß wie der, den die Anwendung bei
>> der *Kommunikation* mit der Datenbank benutzt.
>
> Naja, aber man kann es sehr leicht annehmen: Wenn ich mit der DB in UTF-
> 8 kommuniziere könnte man annehmen, dass die DB per default auch mit
> UTF-8 antwortet.

Und woher soll MySQL jetzt wissen, daß PHP utf8 spricht? SQL Schlüssel-
wörter sind ASCII, also in latin1 und utf8 gleich. Stringliterale in
utf8 sind auch als latin1 interpretierbar. Es ist schlicht nicht
möglich, utf8 *sicher* als solches zu erkennen. BOM funktioniert in
diesem Zusammenhang nicht.


XL

Re: Zeichensatz

am 11.04.2008 19:24:53 von Axel Schwenke

Claus Reibenstein <4spamersonly@online.de> wrote:
> Axel Schwenke schrieb:
>
>> PS: utf8 ist übrigens *nicht* das kanonisch beste Encoding. Zum
>> einen bedeutet die Tatsache, daß ein Zeichen in utf8 1-3 Bytes
>> lang sein kann, einen nicht unerheblichen Mehraufwand für
>> praktisch alle String-Operationen.
>
> Bis hierhin richtig.
>
>> Zum anderen reserviert MySQL
>> *immer* 3 Byte pro utf8 Zeichen.
>
> Das wäre mir neu. Kannst Du diese kühne Behauptung irgendwie belegen?

Probier es aus. Mach einen Index auf zwei VARCHAR(200) Spalten.
Einmal latin1 und einmal utf8.

> Der Vorteil von UTF-8 ist ja gerade, dass eben _nicht_ immer die volle
> Bytelänge pro Zeichen benötigt wird. Es wäre ziemlich krank, wenn MySQL
> diesen Vorteil nicht nutzen würde.

Es wäre ziemlich krank, wenn MySQL auf bestimmte statistische
Merkmale der Daten spekulieren würde und dann für bestimmte Daten
Fehler lieferte.


XL

Re: Zeichensatz

am 11.04.2008 19:29:15 von unknown

Post removed (X-No-Archive: yes)

Re: Zeichensatz

am 11.04.2008 19:46:05 von Axel Schwenke

Claus Reibenstein <4spamersonly@online.de> wrote:
> Christian Kirsch schrieb:
>
>>> Tip: To save space with UTF8, use VARCHAR instead of CHAR. [...]
>
> Ein deutlicher Hinweis darauf, dass bei VARCHAR _keine_ feste
> Zeichenbreite von 3 Bytes verwendet wird, womit Axels Behauptung
> widerlegt wäre.

Das war nicht mein Punkt. Es geht nicht um den Platzverbrauch realer
Daten auf der Festplatte - der hängt bei UTF8 natürlich von statisti-
schen Merkmalen der Daten ab. Es geht darum, daß ein Record in MySQL
nicht größer als 64KB sein darf. Deswegen erlaubt dir MySQL auch keine
VARCHAR(30000) Spalte im UTF8 Encoding, weil die eben doch mal größer
werden könnte.

Ein Kompromiß für die Speicherung von Unicode in MySQL wäre UCS2.
Das ist sozusagen die native Codierung von Unicode mit 2 Byte pro
Zeichen. Vorteile: VARCHAR(30000) geht wieder. String-Operationen
werden wieder einfacher. Nachteil: die meisten realen Daten aus
dem europäischen Sprachraum nehmen in UCS2 mehr Platz ein als in
UTF8. Weil lange UTF8 Sequenzen statistisch selten auftreten.

Wenn die Daten indisch (Devanagari), Thai oder Japanisch (Hiragana)
sind, sieht das anders aus. Da ist dann UCS2 kürzer als UTF8.
(ab U+0800 braucht UTF8 3 Byte je Code Point)


XL

Re: Zeichensatz

am 11.04.2008 20:10:11 von Axel Schwenke

"Oliver C. Thornton" wrote:
> Di dalam de.comp.datenbanken.mysql Axel Schwenke menulis sebagai
> berikut:
>
>> Dein Vergleich hinkt. PHP sagt MySQL ja gerade nicht, welchen Dialekt
>> es spricht. MySQL nimmt dann einfach an, es wäre latin1.
>
> Aber mySQL weis, dass es Daten in Englisch (UTF-8) hat, warum sollte es
> dann auf Latein antworten?
> Mir gehts darum: Ich gebe doch meiner mySQL-DB per Collation, cefault
> charset etc. vor in welchem format es die daten speichern soll. Was ich
> nicht verstehe: Warum spuckt es nicht per default die daten auch wie
> gespeichert aus sondern braucht dafür eine separate Anweisung?

Weil der Vergleich hinkt. MySQL ist kein Buchladen, der bei der Frage
nach einem Buch ins Regal greift und das Buch in der ersten Sprache
die er findet, rausreicht. MySQL ist ein Buchladen mit angeschlossenem
Übersetzerbüro, der das Buch auf Anfrage in die Sprache übersetzt, von
der er annimmt, daß du sie haben willst, es ausdruckt und rausgibt.

Und wenn du nix anderes sagst, nimmt MySQL halt latin1 an. Irgendeine
Annahme muß es machen, sonst würde es bei einem Join zwischen einer
utf8-Tabelle und einer latin1-Tabelle gar einen Mix ausspucken.

(das war übrigens das Verhalten vor MySQL 4.1 - da hat sich MySQL gar
nicht um das Encoding gekümmert und Daten einfach genauso ausgespuckt
wie es sie mal entgegengenommen hat. Kann man heute auch noch haben -
die Daten einfach als BINARY deklarieren)

>> Und woher soll MySQL jetzt wissen, daß PHP utf8 spricht?
>> Stringliterale in utf8 sind auch als latin1 interpretierbar. Es ist
>> schlicht nicht möglich, utf8 *sicher* als solches zu erkennen.
>
> Braucht es nicht wissen. Es hat daten in UTF-8 gespeichert,

Jaaa. Aber da hat die andere Seite auch gesagt, daß sie utf8 anliefert.
Und übrigens: das würde auch immer noch funktionieren, wenn die andere
Seite latin1 anliefert (und das auch sagt). MySQL wird dann z.B. ein
latin1 "Ü" brav in ein utf8 "Ü" umwandeln, bevor es die Daten auf die
Festplatte schreibt.

> ohne weitere Anweisung erwarte ich, dass es auch UTF-8 ausspuckt.

Eine vollkommen ungerechtfertigte Annahme:
http://dev.mysql.com/doc/refman/5.0/en/charset-connection.ht ml

character_set_results bestimmt, in welchem Encoding der Server
Ergebnisse an den Client ausliefert. Das steht per default auf
latin1 und wird von "set names utf8" auf utf8 gestellt.

Allerdings können MySQL-Clients ein default-Connection-Encoding
benutzen, z.B. indem sie ein Option-File verwenden und dort
default-character-set setzen. Die 'mysqli' Extension für PHP
unterstützt das auch, ich habe es aber noch keinen PHP-Anwender
nutzen sehen.

Fvaq unyg nyyrf Synpucsrvsra, qvr CUC orahgmra. FPAE ;-)


XL

Re: Zeichensatz

am 11.04.2008 20:31:58 von Carsten Wiedmann

Oliver C. Thornton schrieb:
>> Dein Vergleich hinkt. PHP sagt MySQL ja gerade nicht, welchen Dialekt
>> es spricht. MySQL nimmt dann einfach an, es wäre latin1.
>=20
> Aber mySQL weis, dass es Daten in Englisch (UTF-8) hat, warum sollte es=
=20
> dann auf Latein antworten?
> Mir gehts darum: Ich gebe doch meiner mySQL-DB per Collation, cefault=20
> charset etc. vor in welchem format es die daten speichern soll. Was ich=
=20
> nicht verstehe: Warum spuckt es nicht per default die daten auch wie=20
> gespeichert aus sondern braucht dafür eine separate Anweisung?

Viellcht mal eine andere Erklärung:
Bei einer Verbindung sagt der Client dem Server (!) welches Charset er ha=
ben=20
will und selbst benutzt. Grundsätzlich ist das aber erstmal Latin1, da =
bei=20
einer Standardkompilierung von Server und Client das Defaultcharset auf=20
Latin1 gesetzt wird.

Im Server sagst du dann erst in der "my.cnf"=20
(default-character-set/Abschnitt "mysqld"), das der Server "utf-8" für =
neune=20
DB's, Tabellen usw. nehmen soll.

Der Client schickt zu diesem Zeitpunkt immer noch den Hinweis: "Ich will =

Latin1". Ändern kannst du dieses verhalten durch z.B.:
a) in der "my.cnf" (default-character-set/Abschnitt "client")
b) als erstes Kommando "SET NAMES" verwenden.

Version a) funktioniert jetzt aber nicht in jedem Fall, da ein Programm, =
wie=20
z.B. PHP, beim Benutzen der Client-Library (libmysql) nicht unbedingt die=
=20
"my.cnf" verwendet. In diesem Fall muss man also "SET NAMES" verwenden, d=
a=20
sonst der im Client einkompilierte Standard "Latin1" benutzt wird.

Gruß
Carsten

Re: Zeichensatz

am 11.04.2008 20:31:59 von Claus Reibenstein

Axel Schwenke schrieb:
> Claus Reibenstein <4spamersonly@online.de> wrote:
>> Axel Schwenke schrieb:
>>
>>> PS: utf8 ist übrigens *nicht* das kanonisch beste Encoding. Zum
>>> einen bedeutet die Tatsache, daß ein Zeichen in utf8 1-3 Bytes
>>> lang sein kann, einen nicht unerheblichen Mehraufwand für
>>> praktisch alle String-Operationen.
>>
>> Bis hierhin richtig.
>>
>>> Zum anderen reserviert MySQL
>>> *immer* 3 Byte pro utf8 Zeichen.
>>
>> Das wäre mir neu. Kannst Du diese kühne Behauptung irgendwie belegen?
>
> Probier es aus. Mach einen Index auf zwei VARCHAR(200) Spalten.

Bei Index weiß ich's. Brauche ich nicht auszuprobieren.

Deine Behauptung lautet, dass es _immer_ so wäre.

>> Der Vorteil von UTF-8 ist ja gerade, dass eben _nicht_ immer die volle
>> Bytelänge pro Zeichen benötigt wird. Es wäre ziemlich krank, wenn MySQL
>> diesen Vorteil nicht nutzen würde.
>
> Es wäre ziemlich krank, wenn MySQL auf bestimmte statistische
> Merkmale der Daten spekulieren würde und dann für bestimmte Daten
> Fehler lieferte.

Du sprichst in Rätseln.

Gruß. Claus

Re: Zeichensatz

am 11.04.2008 20:48:38 von unknown

Post removed (X-No-Archive: yes)

Re: Zeichensatz

am 11.04.2008 20:51:27 von unknown

Post removed (X-No-Archive: yes)

Re: Zeichensatz

am 11.04.2008 22:09:00 von Axel Schwenke

"Oliver C. Thornton" wrote:
> Di dalam de.comp.datenbanken.mysql Axel Schwenke menulis sebagai
> berikut:
>
>> Weil der Vergleich hinkt.
....

> Ja, aber wie kommt mySQL zur Annahme ich könnte latin wollen wenn in den
> Regalen alle Bücher in UTF-8 stehen?

Ich merke schon. Es ist echt schwer, einen Vergleich zu finden,
der nicht hinkt.

Die Sache ist halt, daß für MySQL keine Verbindung besteht zwischen
dem Encoding von Daten in den Tabellen und dem Encoding, in dem es mit
dem Client redet. Es benutzt das Daten-Encoding nur, um die richtige
Konvertierung auszuwählen.

Du scheinst irgendwie anzunehmen, daß das Client-Encoding nach dem
Öffnen der Verbindung NULL ist und MySQL sich den Wert dann nach den
ersten angefragten Daten aussucht. Das ist aber nicht so. Entweder der
Client sagt das Encoding explizit an (z.B. per Option-File: my.cnf)
oder MySQL nimmt den Default. Und der ist nun mal latin1.

>> (das war übrigens das Verhalten vor MySQL 4.1 - da hat sich MySQL gar
>> nicht um das Encoding gekümmert und Daten einfach genauso ausgespuckt
>> wie es sie mal entgegengenommen hat. Kann man heute auch noch haben -
>> die Daten einfach als BINARY deklarieren)
>
> DAS ist die Antwort warum ich mit der Umstellung auf aktuelles mySQL
> plötzlich nurnoch Zeichensalat hatte :)

Manchmal hilft es, Releasenotes zu lesen.

> Ich kann mir irnkwie nicht vorstellen, dass ich wirklich der einzige bin
> der es vernünftig findet Daten so auszugeben wie sie
> eingegeben/gespeichert wurden; es sei denn es wird explizit was anderes
> gefordert.

Das neue Konzept ist *wesentlich* flexibler. Mit dem alten Konzept
konnte man z.B. nur eine einzige Sortierreihenfolge für den ganzen
MySQL-Server haben. Jetzt kann man für jede Spalte eine Default-
Sortierreihenfolge vorgeben und extra noch in der Query per COLLATE.

> Dann habe ich die charsets/collations nicht verstanden.

Endlich stimmen wir mal überein! ;-)

Ich geb ja zu, ich hab auch mehr als einen Anlauf gebraucht, um das
Konzept hinter dem 4.1 Zeichensatz-Handling zu verstehen. Es lohnt
sich aber.

> Ich dachte mit
> der collation schreibe ich auf das Bücherregal: Hier nur UTF-8 Bücher.
> Wenn ich da jetzt latin-Bücher reinstelle werden die trotzdem in UTF-8
> ins Regal gestellt (dann halt mit Zeichensalat, ist ja auch das Falsche
> Regal)

Wir hatten zwar schon festgestellt, daß der Buchvergleich hinkt,
aber meinetwegen. Das Problem ist, daß du bei MySQL das Schild
"UTF8" nicht an das Regal heftest. Sondern daß jedes Kapitel in
jedem Buch (jede Spalte in jeder Tabelle) sein eigenes Encoding
definiert. Oder zumindest definieren kann. Und jedes Buch (Tabelle)
kann einen Default vorgeben, der genommen wird wenn das Kapitel
(Spalte) nix definiert. Und wenn das Buch auch nix sagt, gilt der
Default des Regals (Datenbank) und im Zweifelsfall der Default des
Ladens (Server).

Leider endet hier der Buchvergleich. Ein Buchverkäufer würde dich
in dieser Situation fragen "In welcher Sprache darfs denn sein?".
MySQL mag aber nicht bei jeder Query nachfragen, sondern verläßt
sich darauf, daß du beim Betreten des Geschäfts einen Button aus
dem "English" oder "Deutsch" Korb genommen und dir angesteckt hast.
Und wenn du keinen Button hast, wählt es halt "Englisch".

>> Allerdings können MySQL-Clients ein default-Connection-Encoding
>> benutzen, z.B. indem sie ein Option-File verwenden und dort
>> default-character-set setzen.
>
> default-character-set hab ich auf utf-8, zeigt nur keinerlei Wirkung.

Weil PHP kaputt ist. Mancher mag das schade finden, andere zucken
nur mit den Schultern und sagen: "Und, was ist daran neu?"

Ich hab jetzt seit etlichen Jahren nichts mehr mit PHP machen müssen.
Aber eigentlich hätte ich erwartet, daß die diversen Frameworks, die
man typischerweise über die nackte Datenbankverbindung stülpt, einem
eine "ich will Encoding XYZ" Option anbieten.

> Ich habe einklich in jeder auffindbaren config/option/collation/charset
> etc. jedes latin/ISO/sonstwas gegen utf-8 ausgetauscht, das set names
> brauche ich dennoch und das finde ich irgendwie, naja, überflüssig.

Siehste mal. Wenn du *vorher* gefragt hättest, dann hätten wir dir
sagen können daß genau umgekehrt ein Schuh draus wird. Wenn du deine
Applikation auf utf8 umstellst, mußt du dazu genau gar nix an der
Datenbank ändern (es sei denn, du willst jetzt zusätzlich noch Daten
ablegen die nicht in latin1 passen). Einfach "SET NAMES utf8" und ab
sofort spricht MySQL mit dir utf8.

Wenn das nicht elegant ist, dann weiß ich auch nicht weiter.


XL

Re: Zeichensatz

am 11.04.2008 22:18:37 von Axel Schwenke

Claus Reibenstein <4spamersonly@online.de> wrote:
> Axel Schwenke schrieb:
>> Claus Reibenstein <4spamersonly@online.de> wrote:
>
>>> Der Vorteil von UTF-8 ist ja gerade, dass eben _nicht_ immer die volle
>>> Bytelänge pro Zeichen benötigt wird. Es wäre ziemlich krank, wenn MySQL
>>> diesen Vorteil nicht nutzen würde.
>>
>> Es wäre ziemlich krank, wenn MySQL auf bestimmte statistische
>> Merkmale der Daten spekulieren würde und dann für bestimmte Daten
>> Fehler lieferte.
>
> Du sprichst in Rätseln.

Na nimm doch einfach mal an, MySQL würde dir erlauben eine Spalte
VARCHAR(30000) CHARSET utf8 zu definieren. Das wird eine ganze Weile
gut gehen. Bis irgendwann einer auf die Idee kommt, da 25.000 Zeichen
Thai drin speichern zu wollen. Blöderweise braucht Thai in utf8 aber
3 Byte pro Zeichen, das sind dann 75.000 Bytes. Und schon knallt es,
weil ein Record (und noch viel mehr eine einzelne Spalte) nicht größer
als 64KB sein darf. Die Datenbank würde funktionieren oder nicht, in
Abhängigkeit von den Daten.

Und weil sowas keiner will, macht MySQL auf pessimistisch und sagt
"Njet! Mach deine VARCHARs kürzer! So kurz, daß sie jedem Fall weniger
als 64KB lang sind."


XL

Re: Zeichensatz

am 12.04.2008 17:05:42 von Claus Reibenstein

Axel Schwenke schrieb:

> Claus Reibenstein <4spamersonly@online.de> wrote:
>
>> Axel Schwenke schrieb:
>>
>>> Es wäre ziemlich krank, wenn MySQL auf bestimmte statistische
>>> Merkmale der Daten spekulieren würde und dann für bestimmte Daten
>>> Fehler lieferte.
>>
>> Du sprichst in Rätseln.
>
> Na nimm doch einfach mal an, MySQL würde dir erlauben eine Spalte
> VARCHAR(30000) CHARSET utf8 zu definieren.

Ok, jetzt weiß ich, worauf Du hinaus willst.

Dieser Fall tritt natürlich nicht ein, weil MySQL genau das verbietet,
da es hier vom "worst case" ausgeht, dass jedes Zeichen 3 Byte benötigen
würde (meintest Du das mit "reserviert MySQL *immer* 3 Byte pro utf8
Zeichen"?).

Gruß. Claus

Re: Zeichensatz

am 12.04.2008 18:54:44 von Dirk Ohme

Carsten Wiedmann schrieb im Newsbeitrag
> Der Client schickt zu diesem Zeitpunkt immer
> noch den Hinweis: "Ich will Latin1". Ändern
> kannst du dieses verhalten durch z.B.:
a) in der "my.cnf" (default-character-set/Abschnitt "client")
b) als erstes Kommando "SET NAMES" verwenden.

Eigentlich kann der Client es auch über die API angeben und PHP kennt
bei MySQL und mysqli jeweils ein mysql_set_charset(). Das wäre also
noch Option C.

Gruß, Dirk

Re: Zeichensatz

am 12.04.2008 23:49:59 von Carsten Wiedmann

Dirk Ohme schrieb:
> Carsten Wiedmann schrieb im Newsbeitrag
> b) als erstes Kommando "SET NAMES" verwenden.
>=20
> Eigentlich kann der Client es auch über die API angeben und PHP kennt=
=20
> bei MySQL und mysqli jeweils ein mysql_set_charset(). Das wäre also n=
och=20
> Option C.

Da b) einfach dafür steht: "Client setzt Charset selbst und nicht übe=
r=20
Vorgabe in einer 'my.cnf'", wäre mysql(i)_set_charset dann eher "b) 2."=
Als=20
"b) 1." würde man das Charset dann gleich in den Verbindungsoptionen=20
angeben, und als letzte Möglichkeit ("b) 3.") dann über "SET NAMES". =
"SET=20
NAMES" hat ja den Nachteil, dass es bei mysql_real_escape_string() nicht=
=20
greift...

Gruß
Carsten