2013-01-03 11 views
9

Ich suche eine Datenbank von Weinnamen abzufragen, von denen viele enthalten Akzente (aber nicht in einer einheitlichen Art und Weise, und so ähnliche Weine mit oder ohne Akzente eingegeben werden können)MySQL REGEXP Abfrage - Akzent unempfindliche Suche

die grundlegende Abfrage sieht wie folgt aus:

SELECT * FROM `table` WHERE `wine_name` REGEXP '[[:<:]]Faugères[[:>:]]' 

die Einträge mit 'Faugères' im Titel zurück, aber nicht 'Faugeres'

SELECT * FROM `table` WHERE `wine_name` REGEXP '[[:<:]]Faugeres[[:>:]]' 

das Gegenteil der Fall ist.

Ich hatte gedacht, so etwas wie:

SELECT * 
FROM `table` 
WHERE `wine_name` REGEXP '[[:<:]]Faug[eèêéë]r[eèêéë]s[[:>:]]' 

könnte den Trick tun, aber dies gibt nur die Ergebnisse ohne die Akzente.

Das Feld ist als utf8_unicode_ci sortiert, was von dem, was ich gelesen habe, ist, wie es sein soll.

Irgendwelche Vorschläge ?!

+0

hatte ich das gleiche Problem. Schauen Sie sich mein Thema hier: http://stackoverflow.com/questions/33722136/how-to-search-string-using-entity-framework-with-contains-and-with-accent-insen/34047990#34047990 – Dan

Antwort

4

You're out of luck:

Warnung

Die REGEXP und RLIKE Operatoren arbeiten in Byte-weise Art und Weise, so dass sie nicht multibytesicher und kann zu unerwarteten Ergebnissen mit Multi-Byte- produzieren Zeichensätze. Außerdem vergleichen diese Operatoren Zeichen nach , deren Byte-Werte und akzentuierte Zeichen möglicherweise nicht als gleichwertig verglichen werden, selbst wenn eine gegebene Kollatierung sie als gleich behandelt.

Die [[:<:]] und [[:>:]] regexp Operatoren sind Marker für Wortgrenzen. Die nächstgelegene Sie mit dem LIKE Operator erreichen können, ist etwas auf dieser Linie:

SELECT * 
FROM `table` 
WHERE wine_name = 'Faugères' 
    OR wine_name LIKE 'Faugères %' 
    OR wine_name LIKE '% Faugères' 

Wie Sie es nicht völlig gleichwertig sehen, weil ich das Konzept der Wortgrenze auf Räume beschränkt haben. Das Hinzufügen von mehr Klauseln für andere Grenzen wäre ein Durcheinander.

Sie könnten auch Volltextsuchen verwenden (obwohl es nicht dasselbe ist), aber Sie können (noch) keine Volltextindizes in InnoDB-Tabellen definieren.

Sie sind sicherlich kein Glück :)

+0

Ouch. .. - OK, also, wenn ich umstelle: WHERE 'wein_name' LIKE '% Faugeres%' gibt es irgendwelche Nachteile? Ich kann mich nicht daran erinnern, warum wir mit REGEXP waren zu beginnen, aber ich glaube, es war mit der Suche nach ganzen Wörtern zu tun und nicht Strings innerhalb von Worten, die die oben wie Anweisung tun würde ... – freestate

+0

Diese Lösung ist nicht so gut sein kann, weil es wird nicht funktionieren, wenn das Wort andere Buchstaben davor oder davor hat, wie: "Faugères." "Faugères!" "Faugères?" (Faugères' und viele andere Variationen. Ich suche das Gleiche: REGEXP, um Wortgrenzen zu verwenden, aber akzentunempfindlich. – steps

1

utf8_general_ci sehen keinen Unterschied zwischen Akzent/ohne Akzent beim Sortieren. Vielleicht gilt das auch für Suchanfragen. Ändern Sie auch REGEXP zu LIKE. REGEXP macht einen binären Vergleich.

0

Ok, ich bin gerade auf diese Frage gestoßen, als ich nach etwas anderem gesucht habe.

Dies ist wahr.

SELECT 'Faugères' REGEXP 'Faug[eèêéë]+r[eèêéë]+s'; 

Ich hoffe, es hilft.

Hinzufügen des '+' Zeigt den regulären Ausdruck an, um nach einem oder mehreren Vorkommen der Zeichen zu suchen.

0

Um dieses Problem zu lösen, habe ich verschiedene Dinge ausprobiert, einschließlich der Verwendung des binären Schlüsselworts oder des Zeichensatzes latin1, aber ohne Erfolg.
Schließlich, wenn man bedenkt, dass es ein MySql Bug ist, landete ich die e und e Zeichen ersetzt auf,

So:

SELECT * 
FROM `table` 
WHERE replace(replace(wine_name, 'é', 'e'), 'è', 'e') REGEXP '[[:<:]]Faugeres[[:>:]]' 
3

Da REGEXP und RLIKE sind byteorientiert, haben Sie versucht:

SELECT 'Faugères' REGEXP 'Faug(e|è|ê|é|ë)r(e|è|ê|é|ë)s'; 

Dies sagt, einer von diesen muss in dem Ausdruck sein. Beachten Sie, dass ich nicht auf das Plus verwendet habe (+), denn das bedeutet eine oder mehr. Da Sie nur einen wollen, sollten Sie das Plus nicht verwenden.

0

Ich hatte das gleiche Problem versucht, jeden Datensatz zu finden, der einem der folgenden Muster entsprach: 'copropriété', 'copropriete', 'COPROPRIÉTÉ', 'Copropri? T?'

REGEXP 'copropri.{1,2}t.{1,2} arbeitete für mich. Grundsätzlich .{1,2} Willen sollten in jedem Fall arbeiten, ob das Zeichen gleich 1 oder 2 Byte kodiert.

Erläuterung: https://dev.mysql.com/doc/refman/5.7/en/regexp.html

Warnung
Die REGEXP und RLIKE Operatoren arbeiten in Byte-weise Art und Weise, so dass sie nicht sicher multibyte und unerwartete Ergebnisse mit Mehrbyte-Zeichensätzen erzeugen kann. Darüber hinaus vergleichen diese Operatoren Zeichen durch ihre Byte-Werte und akzentuierte Zeichen vergleichen, können nicht als gleich selbst wenn eine bestimmte Sortierungs sie als gleich behandelt.