Глиф Учебники

Поиск по части текста — LIKE

Справочник · SQL · 2 минуты чтения

SQL
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:

SQL
SELECT name FROM products WHERE name ILIKE '%ноут%';

В SQLite функции lower() и upper() тоже меняют регистр только у латинских букв: lower('ПЕНАЛ') вернёт ПЕНАЛ. Варианты для русского текста в SQLite:

Знак % или _ в самом тексте

Чтобы найти буквально «50%», перед знаком ставят символ экранирования и называют его словом ESCAPE:

SQL
SELECT 'Скидка 50%' LIKE '%50!%%' ESCAPE '!';

Ответ — «да» (SQLite показывает его как 1): !% значит «настоящий знак процента», а последний % — по-прежнему «что угодно». Так же !_ — настоящее подчёркивание, важное при поиске имён вроде file_1. Символ экранирования можно выбрать любой, которого нет в искомом тексте; восклицательный знак удобен тем, что одинаково работает во всех СУБД. В MySQL и PostgreSQL без ESCAPE экранирует обратная косая черта: LIKE '%50\%%'.

Слово из программы

Если искомое слово передаётся параметром, знаки % добавляют склейкой:

SQL
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 и ~).