Я хочу найти в своей базе данных любую строку, содержащую эмодзи бабочки - ? - с помощью regexp.
Например
SELECT *
FROM `table`
WHERE `text`
REGEXP '?'
Я использую REGEXP, потому что могу найти Hello[[:space:]]world или аналогичный.
Я получаю ошибку
Got error 'nothing to repeat at offset 0' from regexp
Это работает:
SELECT *
FROM `table`
WHERE `text`
LIKE '%?%'
Но потом теряю возможность искать, скажем, flying[[:space:]]?
Моя подборка - utf8mb4_unicode_ci. База данных - 10.0.36-MariaDB
Если он использует utf-16, вы должны использовать суррогатную пару '\uD83E\uDD8B', в противном случае используйте кодовую точку '\U0001F98B'
@sln - в вопросе используется текст в кодировке UTF-8 (шестнадцатеричный F09FA68B), а не в формате UTF-16. Не используйте коды CHARACTER SET utf16 или \u.
Это может быть кодировка текста исходного кода MySQL, что означает, что вы должны использовать кодовые точки в регулярном выражении, что всегда лучше. @RickJames - исходный текст регулярного выражения не представлен с помощью байтовый код. Они представляют собой КОДЕПИНТЫ, который устраняет двусмысленность от источника кодирования как исходного, так и целевого текстов регулярного выражения. Обычно это обрабатывается как Персонаж, тогда как целевая кодировка для этого модуля является непрозрачной фоновой задачей при запуске механизма. \uXXXX\u{XX}\x{XX} кодируют независимые конструкции CODEPOINT.
@sln - \uD83E\uDD8B для MySQL составляет 10 байтов ascii. \u превращается в u. Обратите внимание на отсутствие \u на dev.mysql.com/doc/refman/8.0/en/string-literals.html. мая означает, что клиент интерпретирует кодовые точки. SELECT LENGTH('\uD83E\uDD8B'); -> 10. См. Также HEX() и CHAR_LENGTH().
@sln - Сюжет сгущается. SELECT HEX('\U+1F98B'); -> F09FA68B. (Обратите внимание на добавленный +.) Но \U+0034 действует как строка ascii. Мне нужно почесать затылок.
@RickJames - Хорошо, мало исследовал. Num 1: при использовании версии MySQL 8.0.4 или выше используется механизм регулярных выражений ICU. Num 2: необходимо избежать обратной косой черты, чтобы получить обратную косую черту для двигателя. Число 3: Нотация кодовых точек в ICU использует конструкцию \x{}. Num 4: Необходимо использовать ключевое слово REGEXP. Num 5: иногда цель находится в UTF-16, в противном случае - в UTF-8/32. Итак, если у вас есть известный mbcs, сначала преобразуйте его в 8/16/32. Поместив это на место, попробуйте это. REGEXP '\\x{D83E}\\x{DD8B}' или REGEXP '\\x{1F98B}'






Честно говоря, я не знаю почему, но побег от бабочки даст желаемый результат. (По крайней мере, в моей версии MariaDB 10.3.10, которая выдавала ту же ошибку без экранирования).
SELECT * FROM `table` WHERE `text` REGEXP '\\?'
(обратите внимание на двойную обратную косую черту, первая - для экранирования обратной косой черты внутри строки, что дает регулярное выражение \?)
Интересный. Когда я пытаюсь это сделать, он находит любой текст с символом ?, а также текст с символом ?. Очень странно! Ваш ответ приближает меня, но он мне не подходит.
@TerenceEden: Я не могу воспроизвести проблему, см. dbfiddle.
Эта рабочий пример использует MariaDB 10.3.11. Я использую 10.0.36. Подозреваю, поэтому.
Я также использовал 10.3 с той же ошибкой (хотя я получил эту ошибку только на регулярном выражении с одной бабочкой, а не с префиксом flying[[:space:]]). Может какая-то настройка сервера или подключения? Или, может быть, в моем случае PhpMyAdmin идет не так ...
Это помогло мне найти (foo|?|baz) на MariaDB 10.1.44. При переходе на (foo|\\?|baz) поиск выполнялся без ошибок, как и ожидалось. Все наборы символов (клиент, база данных и т. д.) Уже были правильно установлены в каждом случае.
SHOW VARIABLES LIKE 'char%';
Похоже, вы не сказали MySQL, какую кодировку клиент использует для символов. Лучше всего это сделать через параметры подключения или через mysqli_charset (при использовании mysqli, а не PDO).
Также запустите это в своей версии:
SELECT 'ab' REGEXP '?';
Я подозреваю, что это даст вам то же сообщение об ошибке.
Показать переменные дает character_set_client utf8mb4 character_set_connection utf8mb4 character_set_database latin1 character_set_filesystem двоичный character_set_results utf8mb4 character_set_server latin1 character_set_system utf8 character_sets_dir / usr / share / mysql / charsets / Так это выглядит правильно? Вы правы насчет ошибки в инструкции select.
Да, похоже, правильно. См. «Вопросительный знак» в stackoverflow.com/questions/38363566/…
Советую прочитать Почему я должен предоставлять MCVE для того, что мне кажется очень простым запросом SQL?