MySQL 5.0 - UTF-8 - SELECT - Umlaute
Gunther
- datenbank
Hallo Selfgemeinde!
Es ist wieder mal soweit - ich brauche eure geschätzte Hilfe.
Ich habe mein aktuelles Projekt komplett in UTF-8 kodiert, u.a. auch meine MySQL DB (also die darin enthaltenen Tabellen, Spalten, Daten).
Nun habe ich u.a. eine Spalte (Kollation = utf8_unicode_ci), die Einträge mit Umlauten enthalten kann. Bei einer Suche nach diesen Einträgen habe ich nun das Problem, dass die Umlaute zwar mit dem jeweiligen Buchstaben ohne die Pünktchen drüber gleichgesetzt werden (also bspw. über == uber), aber nicht mit der eigentlich im Deutschen üblichen Ersatzschreibweise 'Buchstabe ohne Pünktchen + e' (Ausnahme: ß = ss).
Nachforschungen im Netz haben mich zu der Erkenntnis gebracht, dass das mit MySQL ab Version 5.1 wohl möglich sein wird, weil dann auch utf8_german2_ci unterstützt wird.
Da ich aber noch mit MySQL 5.0 auskommen muss, meine Frage:
Gibt es eine Möglichkeit, ein solches Suchverhalten auch für diese Version zu erstellen?
Und wenn ja, wie sähe diese aus?
Für eure Hilfe wie immer meinen besten Dank im Voraus.
Gruß Gunther
Hi!
Nachforschungen im Netz haben mich zu der Erkenntnis gebracht, dass das mit MySQL ab Version 5.1 wohl möglich sein wird, weil dann auch utf8_german2_ci unterstützt wird.
Da gibt es mehrere Erklärungsmöglichkeiten:
Da ich aber noch mit MySQL 5.0 auskommen muss, meine Frage:
Gibt es eine Möglichkeit, ein solches Suchverhalten auch für diese Version zu erstellen?
Gemäß Handbuch gibt es da für Unicode-basierende Kodierungen nichts. Beim Abfragen nach latin1_* konvertieren und dann vergleichen ist sicher möglich, aber garantiert nicht performant. Der Zeichenverlust beim Konvertieren kommt noch hinzu, doch der ist verkraftbar, wenn du nur (Latin1-)Buchstaben enthaltende Zeichenfolgen suchst.
Lo!
Hi!
Nachforschungen im Netz haben mich zu der Erkenntnis gebracht, dass das mit MySQL ab Version 5.1 wohl möglich sein wird, weil dann auch utf8_german2_ci unterstützt wird.
Da gibt es mehrere Erklärungsmöglichkeiten:
- du hast nicht genau gelesen,
- du hast eine Falschaussage gelesen,
- das MySQL-Handbuch ist fehlerhaft,
- in den Unicode Character Sets gibt es im Gegensatz zu den West European Character Sets tatsächlich kein *_germanX_* (auch in der 5.4-Version des Handbuchs steht nichts darüber).
Hmmm ..., das ist wohl maßgeblich eine Frau Susanne Ebrecht von Sun Microsystems, die diese Info "verbreitet" (oder doch nur Feature Request) - egal! ;-)
Da ich aber noch mit MySQL 5.0 auskommen muss, meine Frage:
Gibt es eine Möglichkeit, ein solches Suchverhalten auch für diese Version zu erstellen?Gemäß Handbuch gibt es da für Unicode-basierende Kodierungen nichts. Beim Abfragen nach latin1_* konvertieren und dann vergleichen ist sicher möglich, aber garantiert nicht performant. Der Zeichenverlust beim Konvertieren kommt noch hinzu, doch der ist verkraftbar, wenn du nur (Latin1-)Buchstaben enthaltende Zeichenfolgen suchst.
Performance dürfte nicht so ein Problem sein, da es ja nicht die Regel, sondern nur die Ausnahme darstellt (darstellen soll zumindest).
Ich würde das ja nur in dem Fall anstellen, falls die "normale" Suche ergebnislos verläuft.
Mal gucken, ob ich das "gebacken" bekomme! ;-)
Vielen Dank einstweilen für deine, wie immer, hilfreiche Antwort. Ich mach' mich mal daran, dass umzusetzen.
Gruß Gunther
Hi!
Ich nochmal - kriege es nicht gebacken ... .
Gemäß Handbuch gibt es da für Unicode-basierende Kodierungen nichts. Beim Abfragen nach latin1_* konvertieren und dann vergleichen ist sicher möglich, aber garantiert nicht performant. Der Zeichenverlust beim Konvertieren kommt noch hinzu, doch der ist verkraftbar, wenn du nur (Latin1-)Buchstaben enthaltende Zeichenfolgen suchst.
Nochmal kurz zur Erklärung (um Missverständnisse auszuschließen):
Ich habe bspw. in einer Tabelle meiner DB den Eintrag "Überschrift".
Diesen Eintrag möchte ich nun per Query finden.
Stelle ich Kollation der betreffenden Tabellen Spalte auf 'utf8_unicode_ci', dann findet er den Eintrag unter:
Soweit so gut. Nun möchte ich aber_zusätzlich_, falls diese Sucher erfolglos verlief, auch noch nach dem "Muster" von 'latin1_german2_ci' abfragen, damit der Eintrag auch unter
Mein Problem derzeit ist, dass soweit ich alles bisher im Netz gefundene dahingehend verstehe, dass ich meinen Vergleichsstring umwandeln kann für die Query, aber das ja nicht das, was ich brauche.
Ich bräuchte ja eine Variante, die 'on the fly' die Daten in der Tabellen Spalte umwandelt und die Kollation (für die Abfrage) ändert.
Wenn mir jemand noch mal bitte einen Tipp geben könnte, ob und wie das machbar ist, wäre ich sehr dankbar!
Andere (Alternativ-)Frage: Da diese Tabelle keine Millionen von EInträgen enthalten wird, wäre es ggf. sinnvoller, eine zweite Version davon zu erstellen (mit entsprechend anderem Zeichensatz und Kollation)?
Gruß Gunther
PS: Ach so, und falls es da gleich die nächsten Probleme mit geben sollte, oder das sonstwie von Bedeutung ist, ich verwende PHP PDO.
Hallo Gunther,
Mein Problem derzeit ist, dass soweit ich alles bisher im Netz gefundene dahingehend verstehe, dass ich meinen Vergleichsstring umwandeln kann für die Query, aber das ja nicht das, was ich brauche.
hast Du wirklich im Netz gesucht? Wenn ja, warum?
Ich suche in aller Regel nicht, ich finde im Handbuch. Sprich: ich werfe für solche Fragen keine allgemeine Suchmaschine an.
Ich bräuchte ja eine Variante, die 'on the fly' die Daten in der Tabellen Spalte umwandelt und die Kollation (für die Abfrage) ändert.
Using COLLATE in SQL Statements
Wenn mir jemand noch mal bitte einen Tipp geben könnte, ob und wie das machbar ist, wäre ich sehr dankbar!
Ja sicher ist das machbar. Dass es geht und wie es geht, steht im Handbuch. Mit Beispielen :-)
PS: Ach so, und falls es da gleich die nächsten Probleme mit geben sollte, oder das sonstwie von Bedeutung ist, ich verwende PHP PDO.
Nö, das ist ziemlich irrelevant. Allerdings musst Du Dir im Klaren sein, dass Dir PDO hier überhaupt keine Vorteile verschafft. Das Statement ist MySQL-spezifisch. Ich nutzte mysqli, wenn ich die Wahl hätte :-)
Freundliche Grüße
Vinzenz
Hallo Vinzenz,
Mein Problem derzeit ist, dass soweit ich alles bisher im Netz gefundene dahingehend verstehe, dass ich meinen Vergleichsstring umwandeln kann für die Query, aber das ja nicht das, was ich brauche.
hast Du wirklich im Netz gesucht? Wenn ja, warum?
Ich suche in aller Regel nicht, ich finde im Handbuch. Sprich: ich werfe für solche Fragen keine allgemeine Suchmaschine an.
das Handbuch habe ich vorher ebenfalls studiert, was mir aber eben nicht weitergeholfen hat.
Ich bräuchte ja eine Variante, die 'on the fly' die Daten in der Tabellen Spalte umwandelt und die Kollation (für die Abfrage) ändert.
Ich habe den Fall mit WHERE:
SELECT *
FROM t1
WHERE _latin1 'Müller' COLLATE latin1_german2_ci = k;
Das ist aber doch genau der Fall, den ich meinte: Ich will nicht meinen Suchbegriff umwandeln, sondern die jeweiligen Werte in meiner Tabellenspalte.
Alle bisherigen Versuche endeten in einem Fatal error!
So z.B.: General error: 1267 Illegal mix of collations (utf8_unicode_ci,IMPLICIT) and (latin1_german2_ci,EXPLICIT)
Wenn mir jemand noch mal bitte einen Tipp geben könnte, ob und wie das machbar ist, wäre ich sehr dankbar!
Ja sicher ist das machbar. Dass es geht und wie es geht, steht im Handbuch. Mit Beispielen :-)
Ja, auch diese Seite kannte ich schon. Aus der geht aber nur hervor, was ich schon weiß, nämlich die Unterschiede der einzelnen Kollationen.
Also nochmal die ganz konkrete Frage: Wie kann ich nur für die jeweilige Abfrage den Zeichensatz und die Kollation meiner in der Tabelle vorhandenen Werte von utf-8 utf8_unicode_ci nach latin1 latin1_german2_ci ändern?
Mag sein, dass ich auf der Leitung stehe, aber für mich geht das aus dem Handbuch (zumindest noch) nicht hervor.
Gruß Gunther
Hallo,
Ich bräuchte ja eine Variante, die 'on the fly' die Daten in der Tabellen Spalte umwandelt und die Kollation (für die Abfrage) ändert.
Also nochmal die ganz konkrete Frage: Wie kann ich nur für die jeweilige Abfrage den Zeichensatz und die Kollation meiner in der Tabelle vorhandenen Werte von utf-8 utf8_unicode_ci nach latin1 latin1_german2_ci ändern?
here we go:
1. Schritt: eine nette Tabelle mit einer UTF8-Spalte:
CREATE TABLE example
(name VARCHAR(50) CHARACTER SET 'utf8' COLLATE 'utf8_general_ci')
2. Schritt: wir fügen unseren "Müller" in UTF-8 ein
INSERT INTO
example
SET name = 'Müller'
3. Schritt: wir suchen unseren Müller mit dem Suchtext "Mueller"
a) einfach so
SELECT
name
FROM
example
WHERE
name = 'Mueller'
und bekommen erwartungsgemäß eine leere Ergebnismenge
name
---------
(0 Datensätze gefunden)
b) wir konvertieren unsere Spalte in latin1,
weil latin1 die von uns benötigte Kollation latin1_german2 hat.
(Groß- und Kleinschreibung wäre im Moment nicht benötigt):
SELECT
name
FROM
example
WHERE
[link:http://dev.mysql.com/doc/refman/5.0/en/cast-functions.html#function_convert@title=CONVERT](name USING latin1) COLLATE latin1_german2_ci = 'Mueller'
und finden, wie von Dir gefordert, unseren Datensatz:
name
---------
Müller
(1 Datensatz gefunden)
Ich verstehe vermutlich Dein Problem nicht.
Freundliche Grüße
Vinzenz
Hallo Vinzenz!
Ich bräuchte ja eine Variante, die 'on the fly' die Daten in der Tabellen Spalte umwandelt und die Kollation (für die Abfrage) ändert.
Also nochmal die ganz konkrete Frage: Wie kann ich nur für die jeweilige Abfrage den Zeichensatz und die Kollation meiner in der Tabelle vorhandenen Werte von utf-8 utf8_unicode_ci nach latin1 latin1_german2_ci ändern?
here we go:
- Schritt: eine nette Tabelle mit einer UTF8-Spalte:
CREATE TABLE example
(name VARCHAR(50) CHARACTER SET 'utf8' COLLATE 'utf8_general_ci')
Gibt's schon ...
> 2. Schritt: wir fügen unseren "Müller" in UTF-8 ein
>
> ~~~sql
INSERT INTO
> example
> SET name = 'Müller'
>
... und das auch ...
- Schritt: wir suchen unseren Müller mit dem Suchtext "Mueller"
a) einfach so
SELECT
name
FROM
example
WHERE
name = 'Mueller'
>
> und bekommen erwartungsgemäß eine leere Ergebnismenge
... exakt.
> b) wir konvertieren unsere Spalte in latin1,
> weil latin1 die von uns benötigte Kollation latin1\_german2 hat.
> (Groß- und Kleinschreibung wäre im Moment nicht benötigt):
>
> ~~~sql
SELECT
> name
> FROM
> example
> WHERE
> [link:http://dev.mysql.com/doc/refman/5.0/en/cast-functions.html#function_convert@title=CONVERT](name USING latin1) COLLATE latin1_german2_ci = 'Mueller'
>
Perfekt! Das war der "Knackpunkt".
und finden, wie von Dir gefordert, unseren Datensatz:
Wunderbar!
Ich verstehe vermutlich Dein Problem nicht.
Mein Problem war, dass ich nicht die richtige Kombination aus CONVERT, CAST und COLLATE gefunden habe.
Für mich irritierenderweise verwendet das Handbuch (was ich gefunden habe) nämlich immer CAST in Kombination mit COLLATE und das führte bei mir immer nur zu einem Error.
Also besten Dank für die freundliche Hilfe & Unterstützung - Problem gelöst.
Kurze Nachfrage noch zu deiner Aussage im vorherigen Posting, dass du mysqli gegenüber mysql vorziehen würdest: Aus welchen (praktischen) Gründen/ Überlegungen heraus würdest du das tun?
Für mich macht es keinen großen Unterschied, da ich von weder noch eine große Ahnung habe - mich also eh in entweder oder erst vertiefen muss.
Gruß Gunther
Hallo Gunther,
Also besten Dank für die freundliche Hilfe & Unterstützung - Problem gelöst.
den Dank nehme ich gern entgegen. Schön, dass ich Dir erfolgreich helfen konnte.
Kurze Nachfrage noch zu deiner Aussage im vorherigen Posting, dass du mysqli gegenüber mysql vorziehen würdest: Aus welchen (praktischen) Gründen/ Überlegungen heraus würdest du das tun?
wegen des Feature-Vergleiches im Überblick der PHP-Erweiterungen für MySQL. Sobald Du intensiv DBMS-spezifisches SQL schreibst, geht Dir ein wichtiger Vorzug eines Datenbankabstraktionslayers verloren. Also folge ich dem Rat des Herstellers, was bevorzugt verwendet werden sollte. Dies hängt hier sicher mit dem "Most" in den letzten beiden Zeilen zusammen.
Freundliche Grüße
Vinzenz