#Что происходит и когда возникает
В стандартной сборке SQLite оператор LIKE сравнивает буквы без учёта регистра для латинского диапазона ASCII, но для кириллицы «Москва» и «москва» могут не считаться совпадением. SQL-функции lower()/upper() по умолчанию также не делают полного преобразования регистра Unicode. Поэтому проверка LOWER(title) LIKE LOWER(?) часто не исправляет поиск по русскому тексту; нужна выбранная стратегия нормализации или FTS5, учитывающая требования к поиску.
#Возможные причины: как различить
| Возможная причина | Как узнать | Что делать |
|---|---|---|
| LIKE работает только для ASCII без учёта регистраВстроенное сравнение не охватывает весь Unicode. | SELECT 'ПРИВЕТ' LIKE 'привет' возвращает 0, а 'ABC' LIKE 'abc' — 1. | Подобрать Unicode-совместимый механизм. |
| Нужен поиск внутри слова, а включён поиск по токенамFTS5 unicode61 индексирует слова, но обычный MATCH не равен LIKE %подстрока%. | Поиск полного слова проходит, части слова посередине — нет. | Решить, нужен ли поиск по словам, по префиксам или внутри строк. |
| Разная нормализация русских буквРазличия ё/е, Unicode-нормализации и пробелов не устраняются обычным LIKE. | Одинаковые на вид фразы дают разные результаты. | Принять и документировать правила нормализации при индексации и запросе. |
#Пошаговая диагностика и исправление
- Уточните требование поискаЕсли пользователи ищут целое слово, префикс или произвольную часть названия, запишите 2–3 примера с ожидаемыми результатами. Например, поиск «москва» должен находить «Москва»; для поиска «скв» внутри слова потребуется отдельный способ. Без этого легко выбрать быстрый, но неподходящий индекс.
- Проверьте поведение текущей SQLiteОткройте SQL-консоль приложения либо терминал с sqlite3 и выполните диагностический SELECT из примера. Запрос не изменяет данных: два столбца с результатами 1 и 0 показывают, что ASCII сравнивается без учёта регистра, а кириллица — нет. Если результат другой, вероятно, в вашей сборке установлено расширение или пользовательская функция LIKE.
- Проверьте отсутствие опечатки в шаблонеПосмотрите, формирует ли приложение шаблон с % и _ правильно и передаёт ли строку как параметр, а не подставляет её в SQL текстом. Выведите обезличенные параметры запроса в тестовом окружении. Учтите, что % означает любую последовательность символов, _ — один символ; при буквальном поиске таких знаков нужен ESCAPE.
- Если нужно искать отдельные слова, испытайте FTS5В отдельной тестовой базе создайте виртуальную таблицу FTS5 с tokenizer unicode61 (пример ниже). Введите запись «Москва» и проверьте MATCH 'москва': строка должна находиться. Перед переносом проверьте, включён ли модуль FTS5: иначе SQLite сообщит «no such module: fts5». Такой поиск индексирует слова, а не любую подстроку.
- Если требуется поиск произвольных подстрок, выберите отдельный подходДля небольшого каталога разработчик может хранить дополнительную колонку с Unicode-нормализацией по заранее выбранным правилам и сравнивать нормализованные значения, включая запрос. Для больших наборов при наличии подходящей версии SQLite рассмотрите FTS5 trigram, испытайте особенности регистра и поиск коротких строк. Не рассчитывайте, что стандартные lower()/upper() обработают русский Unicode.
- Не меняйте глобальные настройки LIKE на рабочей базеНе используйте PRAGMA case_sensitive_like как «исправление кириллицы»: оно не добавляет Unicode-поддержку и устарело. Изменение семантики LIKE может повлиять на индексы и выражения схемы. Любую замену механизма поиска тестируйте на отдельной копии данных с запросами пользователей.
- Сравните качество и скорость на контрольных фразахПроверьте заглавные/строчные буквы, ё/е, буквы с комбинируемыми символами, короткие поиски и имена с дефисом. Зафиксируйте число совпадений и время ответа на тестовом объёме. Если новый индекс не подходит, откатите изменения к прежней схеме и оставьте прежний поиск, не изменяя исходные тексты.
#Команды и проверочные примеры
SELECT 'ABC' LIKE 'abc' AS ascii_like, 'ПРИВЕТ' LIKE 'привет' AS russian_like;CREATE VIRTUAL TABLE titles_fts USING fts5(title, tokenize='unicode61');
INSERT INTO titles_fts(title) VALUES ('Москва');
SELECT title FROM titles_fts WHERE titles_fts MATCH 'москва';#Как проверить результат
Ищите одинаковую фразу в нескольких вариантах регистра и сравните результаты на контрольном наборе. Для FTS5 проверьте, что слово «москва» находит «Москва», но не считайте подстрочный поиск автоматически реализованным.
#Если не помогло
Если в FTS5 «no such module: fts5», проверьте сборку SQLite через PRAGMA compile_options; и версию драйвера; не загружайте случайные расширения с сайтов. Если нужны правила русской морфологии, FTS5 unicode61 сам по себе не заменяет полноценный морфологический анализ.