В MySQL почему не-ASCII-символ действительно является двумя символами? - PullRequest
1 голос
/ 23 февраля 2012

У меня есть база данных MySQL с кодировкой по умолчанию, установленной на utf8. Так что не должно быть проблем с работой с символами, которые не являются ASCII. Но это кажется немного сложнее, когда дело доходит до регулярных выражений с помощью команды REGEXP.

Я пытаюсь запрашивать записи, основанные на регулярных выражениях, с использованием подстановочных знаков. Функции, которые предлагает MySQL, достаточны для меня, но они кажутся слегка нарушенными в том смысле, что не-ASCII-символы (я пробовал § и °) не соответствуют ни одному символу подстановки, а двум.

Например, если я ищу вики-страницу с именем '§123', которая находится в базе данных, тогда

SELECT * FROM wikipages WHERE title REGEXP '^.123$'

ничего не вернет, но

SELECT * FROM wikipages WHERE title REGEXP '^..123$'

возвращает нужную страницу (обратите внимание на дополнительный символ подстановки).

Для символов ASCII необходим только один символ подстановки. Я предполагаю, что это связано с тем, сколько байтов используется для кодирования символа в utf8. Однако я нахожу это поведение довольно уродливым, поскольку не могу работать с регулярными выражениями, если MySQL не обрабатывает все символы одинаково.

Есть ли на самом деле веская причина, почему она не работает так, как подозревают? А у кого-нибудь есть идеи, как решить мою проблему?

Заранее спасибо!

Ответы [ 2 ]

3 голосов
/ 23 февраля 2012

Внимание

Операторы REGEXP и RLIKE работают побайтово, поэтому они не являются многобайтовыми и могут давать неожиданные результаты с многобайтовыми наборами символов. Кроме того, эти операторы сравнивают символы по их байтовым значениям, и акцентированные символы могут не сравниваться как равные, даже если данное сопоставление рассматривает их как равные.

http://dev.mysql.com/doc/refman/5.1/en/regexp.html

UTF-8 - потенциально многобайтовый набор символов. По сути, попытка сопоставления символов подстановки в REGEXP с символами UTF-8 иногда не удалась.

Вы можете либо искать определенный символ (который будет автоматически расширен до нужного числа байтов), либо использовать сопоставление с шаблоном без регулярного выражения (например, LIKE) для таких вещей, как поиск префикса / постфикса.

1 голос
/ 23 февраля 2012

Вы должны указать наличие подстановочных знаков

Попробуйте

SELECT "§123" REGEXP "^.*123$" - any character 0 - n
SELECT "§123" REGEXP "^.{0,2}123$" - any character 0 - 2

Оба выражения приводят к 1. Кроме того, руководство MySQL предупреждает о многобайтовых символах.и операторы RLIKE работают побайтово, поэтому они не являются многобайтовыми и могут давать неожиданные результаты с многобайтовыми наборами символов.Кроме того, эти операторы сравнивают символы по их байтовым значениям, и акцентированные символы могут не сравниваться как равные, даже если данное сопоставление рассматривает их как равные.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...