Поиск по части текста — LIKE
SELECT name FROM products WHERE name LIKE '%ноут%';LIKE сравнивает текст с шаблоном. Знак % значит «любые знаки, сколько угодно, в том числе ни одного», поэтому '%ноут%' найдёт всё, где внутри есть «ноут»: «Сумка для ноутбука». А вот «Ноутбук» с заглавной буквы SQLite не найдёт — о регистре ниже.
Шаблоны
| Шаблон | Что найдёт |
|---|---|
'Сум%' | начинается с «Сум» |
'%ка' | заканчивается на «ка» |
'%ка%' | содержит «ка» где угодно |
'_ю%' | вторая буква «ю»: знак _ — ровно один любой знак |
'____' | ровно четыре знака |
Без % и _ LIKE работает как обычное равенство. Отрицание — NOT LIKE: WHERE name NOT LIKE '%а%' — названия без буквы «а».
Регистр букв
Здесь СУБД расходятся сильнее всего:
| СУБД | LIKE без учёта регистра? |
|---|---|
| SQLite | только для латиницы: 'Pencil' LIKE 'pen%' верно, а 'Пенал' LIKE 'пен%' — нет |
| MySQL, MariaDB | обычно да, и для русских букв тоже (зависит от сравнения строк — collation столбца) |
| PostgreSQL | нет; без учёта регистра — ILIKE |
В PostgreSQL:
SELECT name FROM products WHERE name ILIKE '%ноут%';В SQLite функции lower() и upper() тоже меняют регистр только у латинских букв: lower('ПЕНАЛ') вернёт ПЕНАЛ. Варианты для русского текста в SQLite:
- искать оба написания:
WHERE name LIKE '%ноут%' OR name LIKE '%Ноут%'; - хранить рядом копию текста в нижнем регистре, которую готовит программа (в Python —
str.lower()), и искать по ней; - подключить расширение ICU, если ваша сборка SQLite его поддерживает.
Знак % или _ в самом тексте
Чтобы найти буквально «50%», перед знаком ставят символ экранирования и называют его словом ESCAPE:
SELECT 'Скидка 50%' LIKE '%50!%%' ESCAPE '!';Ответ — «да» (SQLite показывает его как 1): !% значит «настоящий знак процента», а последний % — по-прежнему «что угодно». Так же !_ — настоящее подчёркивание, важное при поиске имён вроде file_1. Символ экранирования можно выбрать любой, которого нет в искомом тексте; восклицательный знак удобен тем, что одинаково работает во всех СУБД. В MySQL и PostgreSQL без ESCAPE экранирует обратная косая черта: LIKE '%50\%%'.
Слово из программы
Если искомое слово передаётся параметром, знаки % добавляют склейкой:
SELECT name FROM products WHERE name LIKE '%' || ? || '%';Так в SQLite и PostgreSQL; в MySQL — LIKE CONCAT('%', ?, '%'). Если слово вводит посетитель сайта, % и _ в нём тоже станут шаблоном — экранируйте их, если это мешает.
Скорость и полнотекстовый поиск
Шаблон, который начинается с %, не может использовать обычный индекс: СУБД перебирает все строки. На тысячах строк это незаметно, на миллионах — медленно. Поиск по началу ('Сум%') индекс использовать может, но не во всех СУБД и не при любых настройках.
Для поиска слов в больших текстах (статьи, описания товаров) есть полнотекстовый поиск: модуль FTS5 в SQLite, индексы FULLTEXT в MySQL, tsvector и to_tsquery в PostgreSQL. Они ищут по словам, а не по буквам, и работают намного быстрее LIKE '%…%'.
Ещё в SQLite: GLOB
GLOB — шаблон в стиле имён файлов: * вместо %, ? вместо _, и регистр учитывается всегда. WHERE name GLOB 'Р*' найдёт «Ручка» и «Рюкзак». В других СУБД GLOB нет; в MySQL и PostgreSQL для сложных шаблонов есть регулярные выражения (REGEXP и ~).