Чтобы выбрать строки, в которых поле содержит слово, поставьте в WHERE оператор LIKE и обложите слово знаками процента: SELECT * FROM products WHERE name LIKE '%ноутбук%';. Знак % заменяет любое число символов, в том числе ноль, а _ заменяет ровно один символ.
Главный подвох в регистре. PostgreSQL отличает «Ноутбук» от «ноутбук», MySQL по умолчанию нет, а SQLite игнорирует регистр только у латинских букв. Ниже разберём все случаи на одной таблице, а заодно NOT LIKE, поиск по нескольким словам, экранирование и индексы. Если запросы SELECT вам пока в новинку, начните с разбора команды SELECT в MySQL или с общего рассказа о том, как устроен язык SQL.
Синтаксис LIKE и два подстановочных знака

LIKE сравнивает строку с шаблоном и возвращает истину, если строка шаблону подходит. Пишется он внутри WHERE, как и любое другое условие:
SELECT столбцы
FROM таблица
WHERE столбец LIKE 'шаблон';
В шаблоне работают два специальных символа. Всё остальное сравнивается буква в букву.
| Символ | Что заменяет | Шаблон | Подойдёт |
|---|---|---|---|
% |
любое число символов, включая ноль | 'Мышь%' |
«Мышь», «Мышь Logitech M185» |
_ |
ровно один любой символ | 'CB-0_' |
«CB-01», «CB-02», но не «CB-010» |
Шаблон всегда описывает строку целиком. В документации PostgreSQL сказано: «LIKE pattern matching always covers the entire string», поэтому для поиска слова в середине процент нужен с обеих сторон. Без единого % и _ LIKE работает как обычное равенство.
Все примеры ниже идут по такой учебной таблице товаров:
CREATE TABLE products (id INT PRIMARY KEY, name VARCHAR(100), sku VARCHAR(20));
INSERT INTO products VALUES
(1, 'Ноутбук Lenovo IdeaPad 5', 'NB-001'),
(2, 'ноутбук ASUS VivoBook 15', 'NB-002'),
(3, 'Чехол для ноутбука 15,6 дюйма', 'AC-101'),
(4, 'Мышь Logitech M185', 'MS-185'),
(5, 'Клавиатура Logitech K380', 'KB-380'),
(6, 'Монитор Samsung 27, скидка 10%', 'MN-270'),
(7, 'Кабель USB_C 1 м', 'CB-01'),
(8, 'Кабель USB-C 2 м', 'CB-02'),
(9, NULL, 'XX-000');
Запросы мы выполнили в PostgreSQL 17, MySQL 8.0 и SQLite 3.51. Вывод ниже взят из PostgreSQL, а там, где другие СУБД отвечают иначе, это показано отдельно.
Как выбрать строки по шаблону: начало, середина и конец поля
Положение знака процента определяет, где в строке должен стоять искомый кусок. Это самые частые запросы с LIKE, и почти все остальные строятся из них.
Поле начинается с текста
SELECT id, name FROM products WHERE name LIKE 'Ноутбук%';
id | name
----+--------------------------
1 | Ноутбук Lenovo IdeaPad 5
Вторая строка, «ноутбук ASUS…», сюда не попала, потому что PostgreSQL различает заглавную и строчную букву. MySQL на той же таблице вернёт обе строки. Почему так, разберём в разделе про регистр.
Поле содержит слово в любом месте
Так в SQL выглядит проверка «поле содержит текст», которую в других языках называют contains: процент ставится и до, и после слова.
SELECT id, name FROM products WHERE name LIKE '%ноутбук%';
id | name
----+-------------------------------
2 | ноутбук ASUS VivoBook 15
3 | Чехол для ноутбука 15,6 дюйма
Обратите внимание на третью строку. Шаблон '%ноутбук%' находит и «ноутбука», и «ноутбуком»: LIKE ищет кусок строки, границы слов ему безразличны. Если нужно отдельное слово, выручает полнотекстовый поиск, о нём ниже.
Поле заканчивается на текст
SELECT id, name FROM products WHERE name LIKE '%15';
id | name
----+--------------------------
2 | ноутбук ASUS VivoBook 15
Фиксированная длина через подчёркивание
Подчёркивание удобно для артикулов и кодов, где важна позиция символа. Шаблон '__-1%' читается так: два любых символа, дефис, единица, дальше что угодно.
SELECT id, sku FROM products WHERE sku LIKE '__-1%';
id | sku
----+--------
3 | AC-101
4 | MS-185
Шаблоны свободно сочетаются с другими частями запроса. Найденное можно отсортировать через ORDER BY или пересчитать функцией COUNT.
Канал основателя Checkroi Вани Буявца3 800 человек читают мой Телеграм-канал про нейросетиСобрал промпты для Claude Code и ChatGPT, разборы ИИ-инструментов и лайфхаки по продвижению бизнеса в одном местеПрисоединитьсяNOT LIKE и строки с NULL
NOT LIKE переворачивает условие и оставляет строки, которые шаблону не подходят. Посчитаем товары без слова Logitech:
SELECT COUNT(*) FROM products WHERE name NOT LIKE '%Logitech%';
count
-------
6
В таблице девять строк, Logitech встречается в двух, а в ответе шесть, не семь. Пропала строка с name = NULL.
Решение: помнить, что сравнение с NULL даёт не «ложь», а неизвестность. NULL LIKE '%' возвращает NULL, и такую строку не выберет ни LIKE, ни NOT LIKE. Даже WHERE name LIKE '%' вернёт восемь строк, а не девять. Нужны пустые значения в выборке, добавьте их явно: WHERE name NOT LIKE '%Logitech%' OR name IS NULL. Подробнее эта логика разобрана в статье про NULL в SQL.
Регистр букв: где «Ноутбук» и «ноутбук» считаются разными
Один и тот же запрос LIKE '%ноутбук%' на одной таблице вернул в трёх СУБД разное число строк. Причина в том, как каждая из них сравнивает буквы.
| СУБД | Регистр в LIKE | Строк по ‘%ноутбук%’ | Как искать без учёта регистра |
|---|---|---|---|
| PostgreSQL | различает | 2 | ILIKE или LOWER(name) LIKE … |
| MySQL 8.0 | не различает при сопоставлении по умолчанию | 3 | ничего не нужно; для точного регистра COLLATE utf8mb4_0900_as_cs |
| SQLite | игнорирует только у латиницы | 2 | для кириллицы хранить копию в нижнем регистре |
PostgreSQL: ILIKE
В PostgreSQL есть отдельный оператор ILIKE. В той же документации прямо сказано, что его нет в стандарте SQL: «This is not in the SQL standard but is a PostgreSQL extension». В MySQL и SQLite такой запрос упадёт с ошибкой синтаксиса.
SELECT id, name FROM products WHERE name ILIKE '%ноутбук%';
id | name
----+-------------------------------
1 | Ноутбук Lenovo IdeaPad 5
2 | ноутбук ASUS VivoBook 15
3 | Чехол для ноутбука 15,6 дюйма
Переносимый вариант WHERE LOWER(name) LIKE '%ноутбук%' в PostgreSQL дал те же три строки.
MySQL: регистр решает сопоставление
В MySQL 8.0 таблицы по умолчанию создаются с сопоставлением utf8mb4_0900_ai_ci, где ci означает case-insensitive. Справка MySQL называет это прямо: «nonbinary string comparisons are case-insensitive by default». Поэтому 'Ноутбук%' находит и строку со строчной буквы.
Вторая часть названия, ai, означает accent-insensitive. На практике это значит, что 'ёж' LIKE 'еж' в MySQL возвращает 1, а в PostgreSQL false. Для поиска по русским текстам это скорее плюс, но о нём стоит знать. Точное совпадение с регистром даёт другое сопоставление: WHERE name COLLATE utf8mb4_0900_as_cs LIKE '%ноутбук%' вернул две строки, как PostgreSQL. Старый приём LIKE BINARY тоже работает, но MySQL 8.0 отвечает на него предупреждением 1287: «’BINARY expr’ is deprecated».
SQLite: ловушка с кириллицей
В справке SQLite написано: «SQLite only understands upper/lower case for ASCII characters by default». На деле это выглядит так: LIKE '%logitech%' находит «Logitech», а LIKE 'ноутбук%' находит только строку со строчной буквы. И LOWER() тут не спасает: встроенная функция тоже понимает только латиницу, и запрос с ней вернул две строки вместо трёх.
Решение: хранить рядом колонку с текстом, приведённым к нижнему регистру ещё в приложении, и искать по ней. Второй путь подсказывает сама справка: в расширении ICU своя версия LIKE, которая сравнивает без учёта регистра все символы Юникода.
Как найти сам знак процента или подчёркивание
В таблице есть «Кабель USB_C» и «Кабель USB-C». Шаблон '%USB_C%' находит оба, потому что подчёркивание в нём означает «любой символ», а не сам знак.
Чтобы % или _ искался буквально, перед ним ставят экранирующий символ. Надёжнее всего назначить его явно через ESCAPE. Такой запрос одинаково сработал в PostgreSQL, MySQL и SQLite:
SELECT id, name FROM products WHERE name LIKE '%10!%%' ESCAPE '!';
id | name
----+--------------------------------
6 | Монитор Samsung 27, скидка 10%
Короткая запись с обратным слешем, LIKE '%USB\_C%', работает не везде. В PostgreSQL и MySQL слеш служит экранирующим символом по умолчанию, оба вернули только строку 7. В SQLite тот же запрос не нашёл ничего, пока мы не дописали ESCAPE '\'. В SQL Server значения по умолчанию у экранирующего символа тоже нет, справка Microsoft приводит ровно тот же приём с восклицательным знаком.
-- SQLite: без ESCAPE слеш считается обычным символом
SELECT id, name FROM products WHERE name LIKE '%USB\_C%' ESCAPE '\';
id name
-- ----------------
7 Кабель USB_C 1 м
Поиск по нескольким словам сразу

Отдельного синтаксиса для списка шаблонов в стандартном SQL нет, поэтому условия соединяют через AND и OR. Что выбрать, зависит от задачи.
- Все слова есть в поле:
name LIKE '%Logitech%' AND name LIKE '%M185%'. Порядок слов не важен. - Слова идут в заданном порядке:
name LIKE '%Logitech%M185%'. Одно условие вместо двух, но «M185 Logitech» уже не найдётся. - Хотя бы одно слово:
name LIKE '%Lenovo%' OR name LIKE '%ASUS%'.
SELECT id, name FROM products
WHERE name LIKE '%Lenovo%' OR name LIKE '%ASUS%';
id | name
----+--------------------------
1 | Ноутбук Lenovo IdeaPad 5
2 | ноутбук ASUS VivoBook 15
Когда вариантов больше трёх, цепочка OR разрастается. В PostgreSQL её сворачивают в массив: name LIKE ANY (ARRAY['%Lenovo%', '%ASUS%']) для «любого слова» и LIKE ALL (…) для «всех слов». В MySQL то же делает регулярное выражение name REGEXP 'Lenovo|ASUS', в PostgreSQL его аналог name ~ 'Lenovo|ASUS'. Все три запроса вернули те же две строки.
А вот name IN ('%Lenovo%', '%ASUS%') не вернёт ничего. IN сравнивает на точное равенство, и проценты в нём остаются просто символами. Если OR внутри WHERE смешивается с другими условиями, берите его в скобки, иначе AND сработает раньше. А когда строки нужно не отфильтровать, а пометить, LIKE ставят внутрь оператора CASE: CASE WHEN name LIKE '%Logitech%' THEN 'периферия' ELSE 'другое' END.
Индексы: почему запрос с процентом в начале тормозит
На восьми строках разницы не видно. Мы проверили на таблице из 200 тысяч адресов почты с обычным индексом по колонке email в PostgreSQL 17. План запроса показывает команда EXPLAIN, её можно запустить в psql или в любом клиенте, например в DBeaver (как подключить DBeaver к PostgreSQL).
EXPLAIN SELECT * FROM clients WHERE email LIKE 'client777%';
Seq Scan on clients (cost=0.00..3908.00 rows=20 width=24)
Filter: (email ~~ 'client777%'::text)
Индекс есть, а база всё равно перебирает всю таблицу. Причина в том, что база создана с русской локалью, а обычный индекс сравнивает строки по её правилам. По документации PostgreSQL, для такого случая подходит класс операторов text_pattern_ops: он сравнивает строки посимвольно, поэтому годится для LIKE, когда база работает не с локалью C.
CREATE INDEX clients_email_pattern_idx ON clients (email text_pattern_ops);
EXPLAIN SELECT * FROM clients WHERE email LIKE 'client777%';
Index Scan using clients_email_pattern_idx on clients (cost=0.42..8.44 rows=20 width=24)
Index Cond: ((email ~>=~ 'client777'::text) AND (email ~<~ 'client778'::text))
Оценка стоимости упала с 3908 до 8,44. Но с шаблоном '%777@%' этот индекс бесполезен: B-дерево умеет искать только от начала строки, и план снова превращается в Seq Scan.
Решение для процента в начале: триграммный индекс из расширения pg_trgm. В его документации сказано, что поиск по такому индексу работает и для LIKE, причём шаблон «need not be left-anchored».
CREATE EXTENSION pg_trgm;
CREATE INDEX clients_email_trgm_idx ON clients USING gin (email gin_trgm_ops);
EXPLAIN SELECT * FROM clients WHERE email LIKE '%777@%';
Bitmap Heap Scan on clients (cost=21.59..94.69 rows=20 width=24)
Recheck Cond: (email ~~ '%777@%'::text)
-> Bitmap Index Scan on clients_email_trgm_idx (cost=0.00..21.59 rows=20 width=0)
В MySQL на той же таблице картина похожая: шаблон 'client777%' идёт диапазоном по индексу, а '%777@%' заставляет читать индекс целиком. Умение прочитать такой план отличает того, кто пишет запросы, от того, кто их ускоряет. Обычно это уже работа SQL-аналитика или разработчика баз данных.
LIKE или CONTAINS: когда нужен полнотекстовый поиск
По аналогии с другими языками хочется написать CONTAINS, но такой оператор есть не во всех СУБД. В SQL Server это предикат полнотекстового поиска: по справке Microsoft, он ищет «по столбцам полнотекстового индекса». Значит, сначала на колонку нужно построить такой индекс, а для простого поиска по подстроке и в SQL Server берут LIKE.
| Что нужно | Чем искать |
|---|---|
| подстрока в любом месте, короткие поля | LIKE '%текст%' |
| сложный шаблон, варианты через «или» | REGEXP в MySQL, ~ или SIMILAR TO в PostgreSQL |
| отдельные слова и формы слова в длинных текстах | полнотекстовый индекс: CONTAINS в SQL Server, MATCH … AGAINST в MySQL |
В MySQL полнотекстовый поиск выглядит так. Звёздочка в конце слова нашла и «ноутбук», и «ноутбука»:
ALTER TABLE products ADD FULLTEXT INDEX ft_name (name);
SELECT id, name FROM products
WHERE MATCH(name) AGAINST('ноутбук*' IN BOOLEAN MODE);
+----+-------------------------------+
| id | name |
+----+-------------------------------+
| 1 | Ноутбук Lenovo IdeaPad 5 |
| 2 | ноутбук ASUS VivoBook 15 |
| 3 | Чехол для ноутбука 15,6 дюйма |
+----+-------------------------------+
В SQL Server LIKE понимает ещё и квадратные скобки: LIKE '[C-P]arsen' ищет один символ из диапазона, а [^…] исключает его. Это расширение Transact-SQL. В PostgreSQL, MySQL и SQLite внутри LIKE скобки остаются обычными символами: 'Carsen' LIKE '[C-P]arsen' во всех трёх вернул ложь.
Частые ошибки и что с ними делать

- Запрос ничего не находит, хотя данные есть. Обычно в шаблоне забыли процент:
LIKE 'ноутбук'ищет поле, равное слову целиком. Решение:'%ноутбук%'. - В PostgreSQL ошибка «оператор не существует: integer ~~ unknown». LIKE применили к числовой колонке:
WHERE id LIKE '1%'. MySQL и SQLite молча приводят число к строке, PostgreSQL нет. Решение: явное приведениеid::text LIKE '1%'. - Нашлось больше строк, чем ожидали. В искомом тексте есть
_или%, и они сработали как шаблон. Решение: экранировать через ESCAPE, как в разделе выше. - Запрос работает в MySQL и ломается при переезде на PostgreSQL. В нём неявно работало регистронезависимое сравнение MySQL. Решение: ILIKE или LOWER() с обеих сторон.
- NOT LIKE «теряет» строки. Это строки с NULL в колонке. Решение: дописать
OR name IS NULLили заменить пустое значение через функцию COALESCE.
LIKE работает и в соединениях: шаблоном можно отфильтровать строки уже после JOIN нескольких таблиц, правила те же.
Где освоить SQL системно
LIKE закрывает одну задачу: найти строки по куску текста. Аналитику и разработчику каждый день нужны ещё группировки, соединения, оконные функции и чтение планов запросов. Как выглядит путь от первых SELECT до работы, мы расписали в статье о том, как стать SQL-разработчиком, а ниже собрали курсы, где эти темы идут по порядку и с практикой.
| Курс | Школа | Стоимость со скидкой | В рассрочку | Длительность | Обзор курса от Checkroi |
|---|---|---|---|---|---|
| Нейросети для рабочих задач Перейти на сайт курса | 31 290 ₽ | - | 1 месяц | Обзор курса | |
| SQL для анализа данных Перейти на сайт курса | 50 865 ₽ | 6203 ₽/мес. | 2 месяца | Обзор курса | |
| SQL-разработчик: тариф PRO Перейти на сайт курса | 89 900 ₽ | 7491 ₽/мес. | 2 месяца | Обзор курса | |
| SQL-разработчик: тариф Базовый Перейти на сайт курса | 79 900 ₽ | 3329 ₽/мес. | 3 месяца | Обзор курса | |
| Data-Driven подход в разработке продукта: SQL и Yandex DataLens Перейти на сайт курса | 29 990 ₽ | 2999 ₽/мес. | 1 месяц | Обзор курса |
Больше программ — в полном каталоге курсов по SQL




