2010-02-20 19 views
15

Ich möchte in der Lage sein, Anfragen zu tun, die Zeichen mit Akzent normalisieren, so dass zum Beispiel:Normalisierungs akzentuierte Zeichen in MySQL-Abfragen

é, è, and ê 

alle behandelt wie ‚e‘ sind, in Abfragen mit ‚=‘ und wie'. Ich habe eine Zeile mit Benutzername Feld auf "rené" eingestellt, und ich würde gerne in der Lage sein, mit beiden "rene" und "rené" übereinstimmen.

Ich versuche, dies mit der Klausel 'collate' in MySQL 5.0.8 zu tun. Ich erhalte den folgenden Fehler:

mysql> select * from User where username = 'rené' collate utf8_general_ci; 
ERROR 1253 (42000): COLLATION 'utf8_general_ci' is not valid for CHARACTER SET 'latin1' 

FWIW, mein Tisch war mit erstellt:

CREATE TABLE `User` (
    `id` bigint(19) NOT NULL auto_increment, 
    `username` varchar(32) NOT NULL, 
    PRIMARY KEY (`id`), 
    UNIQUE KEY `uniqueUsername` (`username`) 
) ENGINE=InnoDB AUTO_INCREMENT=56790 DEFAULT CHARSET=utf8 
+0

Was passiert, wenn Sie den Tabellenzeichensatz auf 'utf8' ändern? – friedo

+0

friedrich- ist das nicht das was DEFAULT CHARSET = utf8? (Ich habe diese Tabelle nicht wirklich erstellt; ich habe sie über 'show create table User' zurückentwickelt). –

+0

Ja, das ist es, was es tun soll. Ich weiß nicht, warum MySQL das Chartset für latin1 hält, wenn Sie es auf utf8 setzen. – friedo

Antwort

8

Ich würde vorschlagen, dass Sie die normalisierte Versionen auf den Tisch zusätzlich mit dem realen Benutzernamen speichern. Das Ändern der Codierung im laufenden Betrieb kann teuer sein und Sie müssen die Konvertierung für jede Zeile bei jeder Suche erneut durchführen.

Wenn Sie PHP verwenden, können Sie iconv() verwenden, um die Konvertierung zu handhaben:

$username = 'rené'; 
$normalized = iconv('UTF-8', 'ASCII//TRANSLIT', $string); 

Dann würden Sie nur beide Versionen speichern und die normalisierte Version für die Suche und normalen Benutzernamen für die Anzeige verwenden. Vergleichen und Auswählen aus den normalisierten Spalt viel schneller sein, vorausgesetzt, dass Sie den Suchbegriff normalisieren auch:

$search = mysql_real_escape_string(iconv('UTF-8', 'ASCII//TRANSLIT', $_GET['search'])); 
mysql_query("SELECT * FROM User WHERE normalized LIKE '%".$search."%'"); 

Natürlich ist diese Methode möglicherweise nicht durchführbar sein, wenn Sie mehrere Spalten haben, die Normierungen brauchen, aber in Ihrem speziellen Fall das könnte gut funktionieren.

+0

Hmm, ich bin ein wenig misstrauisch, Daten an mehreren Stellen zu halten (DRY), es sei denn, es stellt sich als Engpass heraus. In diesem Fall würde es 3 existierende Felder beinhalten - Benutzername, Vorname und Nachname (ich habe meine Tabellenstruktur sehr vereinfacht, um eine einfache Frage zu stellen). –

+0

Ich benutze PHP nicht arbeiten ... brauchen Sie mehr 1 nächste Zeile 'str_replace ("? ","% ", $ Normalisiert);' .. genießen! – KingRider

2
$normalized = iconv('UTF-8', 'ASCII//TRANSLIT', $string); 

ist eine perfekte php-lösung, aber in mysql? KONVERTIEREN?

in mysql

SELECT 'Álvaro José' as accented, (CONVERT ('Álvaro José' USING ascii)) as notaccented 

Produce:

Álvaro José  ?lvaro Jos? 

betonte Worte ohne akzentuierte Worte nicht umgewandelt wird, ist es nicht gleichwertig ein translit von iconv.

RegExp nicht mit UTF-8 arbeiten.

Keine Lösung.

+1

Dies ist keine Antwort, sondern ein Kommentar mit nützlichen Informationen –

5

ich eine strtr PHP-Funktion/tr Unix-Befehl in MySQL implementiert haben Sie die Quelle bekommen here

können Sie verwenden als:

SELECT tr(name, 'áäèëî', 'aaeei') FROM persons 

oder einige Zeichen abzustreifen

SELECT tr(name, 'áäèëî', null) FROM persons 
9

Der Grund für den Fehler ist nicht die Tabelle, sondern der Zeichensatz Ihrer Eingabe, also der 'René' in Ihrer Anfrage.Das Verhalten hängt von dem character_set_connection Variable:

A SET NAMES 'charset_name' statement is equivalent to these three statements:

SET character_set_client = charset_name; 
SET character_set_results = charset_name; 
SET character_set_connection = charset_name; 

(von http://dev.mysql.com/doc/refman/5.5/en/charset-connection.html)

Beispiel Ausgang::

The character set used for literals that do not have a character set introducer and for number-to-string conversion.

das MySQL-Client verwendet, es SET NAMES Verwendung ändern

mysql> set names latin1; 
Query OK, 0 rows affected (0.00 sec) 

mysql> select * from User where username = 'rené' collate utf8_general_ci; 
ERROR 1253 (42000): COLLATION 'utf8_general_ci' is not valid for CHARACTER SET 'latin1' 

mysql> set names utf8; 
Query OK, 0 rows affected (0.00 sec) 

mysql> select * from User where username = 'rené' collate utf8_general_ci; 
Empty set (0.00 sec) 

Altenatively, kann die Verwendung explizit den Zeichensatz mit einem ‚Zeichensatz Einführungs‘ gesetzt:

mysql> set names latin1; 
Query OK, 0 rows affected (0.00 sec) 

mysql> select * from User where username = _utf8'rené' collate utf8_general_ci; 
Empty set (0.00 sec) 

Ich weiß, diese Frage ist ziemlich alt, aber da Google mich für eine ähnliche Frage hier führte, dachte ich, es verdient noch eine Antwort :)