Как сделать MySQL осведомленным о многобайтовых символах в LIKE и REGEXP?

У меня есть таблица MySQL с двумя столбцами, как с utf8_unicode_ci. Он содержит следующие строки. За исключением ASCII, второе поле также содержит кодовые точки Unicode, такие как U + 02C8 (MODIFIED LETTER VERTICAL LINE) и U + 02D0 (MODIFIED LETTER TRIANGULAR COLON).

word | ipa --------+---------- Hallo | haˈloː IPA | ˌiːpeːˈʔaː 

Мне нужно искать второе поле с LIKE и REGEXP, но MySQL (5.0.77), кажется, интерпретирует эти поля как байты, а не как символы.

 SELECT * FROM pronunciation WHERE ipa LIKE '%ha?lo%'; -- 0 rows SELECT * FROM pronunciation WHERE ipa LIKE '%ha??lo%'; -- 1 row SELECT * FROM pronunciation WHERE ipa REGEXP 'ha.lo'; -- 0 rows SELECT * FROM pronunciation WHERE ipa REGEXP 'ha..lo'; -- 1 row 

Я абсолютно уверен, что данные хранятся правильно, так как это кажется хорошим, когда я его извлекаю и хорошо отображается в phpMyAdmin. Я нахожусь на общем хосте, поэтому я не могу устанавливать программы.

Как я могу решить эту проблему? Если это невозможно: существует ли правдоподобная работа, которая не требует обработки всей базы данных с помощью PHP каждый раз? Есть 40 000 строк, и я не настроен на использование MySQL (или UTF8, если на то пошло). У меня есть только доступ к PHP и MySQL на хосте.

Изменить: существует открытый 4-летний отчет об ошибках MySQL, ошибка № 30241 Проблемы с регулярным выражением , в котором отмечается, что механизм регулярного выражения работает побайтно. Таким образом, я ищу работу.

EDITED включил исправление в действительную критику

Используйте функцию HEX() чтобы сделать ваши байты шестнадцатеричными, а затем используйте RLIKE для этого, например:

 select * from mytable where hex(ipa) rlike concat('(..)*', hex('needle'), '(..)*'); -- looking for 'needle' in haystack, but maintaining hex-pair alignment. 

Нечетные символы unicode последовательно отображают их шестнадцатеричные значения, поэтому вы просматриваете стандартные символы 0-9A-F.

Это работает и для «нормальных» столбцов, вам это просто не нужно.

ps @ Kieren (действительная) точка, адресованная с использованием rlike для принудительного использования пар char

Я не настроен на использование MySQL

Кажется, что Postgres справляется с этим довольно хорошо:

 test=# select 'ˌˈʔ' like '___'; ?column? ---------- t (1 row) test=# select 'ˌˈʔ' ~ '^.{3}$'; ?column? ---------- t (1 row) 

Если вы спуститесь по этой дороге, обратите внимание, что оператор Postgres like на like MySQL. (В Postgres, like , учитывается регистр.)


Для решения, специфичного для MySQL, вы можете работать, привязав некоторую определенную пользователем функцию (возможно, привязать библиотеку ICU ?) К MySQL.

У вас проблемы с UTF8? Исключите их.

Сколько специальных символов вы используете? Вы используете только локализационные буквы, верно? Итак, мой совет: Напишите функцию, которая преобразует spec-символы в обычные символы, например «æ» -> «A» и т. Д., И добавьте столбец в таблицу, в которой хранится это преобразованное значение (вам нужно преобразовать все значения во-первых, и при каждой вставке / обновлении). При поиске вам просто нужно преобразовать строку поиска с той же функцией и использовать ее в этом поле с регулярным выражением.

Если слишком много специальных символов, вы должны преобразовать его в multi-char. 1. Избегайте нахождения «aa» в последовательности «ba ab», используя некоторый префикс, например «@ ba @ ab». 2. Избегайте нахождения «@a» в «@ab» использовать токены фиксированной длины, скажем, 2.