LIKE в SQL — поиск по шаблону с примерами

Коротко

LIKE -- оператор SQL для поиска строк по шаблону. Нужен, когда точное значение неизвестно: найти всех пользователей с почтой на gmail.com, отфильтровать UTM-метки по кампании, выбрать города, начинающиеся на «Моск». На собеседовании по SQL LIKE встречается в задачах на фильтрацию и чистку данных -- вещь базовая, но ошибки в шаблонах допускают часто.

Синтаксис LIKE

SELECT *
FROM users
WHERE email LIKE '%@gmail.com'

LIKE сравнивает строку с шаблоном. В шаблоне два спецсимвола:

Символ Значение Пример Совпадает с
% Любое количество любых символов (включая ноль) 'A%' 'A', 'Anna', 'A123'
_ Ровно один любой символ 'A_' 'Ab', 'A1', но не 'A' и не 'Abc'

Шаблоны можно комбинировать:

-- имя из 4 букв, начинается на 'И'
WHERE name LIKE 'И___'

-- email содержит 'test' где угодно
WHERE email LIKE '%test%'

-- второй символ -- 'a'
WHERE name LIKE '_a%'

NOT LIKE

Инвертирует условие -- все строки, которые не соответствуют шаблону:

SELECT *
FROM users
WHERE email NOT LIKE '%@internal.company.ru'

Удобно для исключения тестовых данных, внутренних аккаунтов, служебных записей.

ILIKE -- регистронезависимый поиск (PostgreSQL)

Стандартный LIKE регистрозависим: 'Anna' LIKE 'anna%' вернёт FALSE. В PostgreSQL есть ILIKE -- работает так же, но игнорирует регистр:

SELECT *
FROM users
WHERE city ILIKE '%москва%'
-- найдёт 'Москва', 'москва', 'МОСКВА'

В MySQL LIKE по умолчанию регистронезависим (зависит от collation таблицы). В SQL Server -- тоже (по умолчанию). В PostgreSQL используйте ILIKE или приведите к одному регистру через LOWER():

WHERE LOWER(city) LIKE '%москва%'

ESCAPE -- если нужен литеральный % или _

Если в данных встречается символ % или _ и нужно искать именно его, укажите escape-символ:

-- найти строки, содержащие '20%'
WHERE description LIKE '%20\%%' ESCAPE '\'

Здесь \% -- это литеральный символ процента, а не шаблон. Без ESCAPE невозможно отличить спецсимвол от обычного.

SIMILAR TO и регулярные выражения (PostgreSQL)

Для сложных шаблонов PostgreSQL предлагает две альтернативы:

SIMILAR TO -- гибрид LIKE и регулярных выражений:

-- email заканчивается на gmail.com или yandex.ru
WHERE email SIMILAR TO '%(gmail.com|yandex.ru)'

Оператор ~ -- полноценные регулярные выражения POSIX:

-- телефон в формате +7XXXXXXXXXX
WHERE phone ~ '^\+7\d{10}$'

-- регистронезависимый вариант: ~*
WHERE name ~* '^(анна|anna)'

Регулярные выражения мощнее, но медленнее LIKE. Используйте их, когда шаблонов % и _ не хватает.

Производительность

Главное правило: LIKE 'abc%' использует индекс, '%abc' -- нет.

Если шаблон начинается с фиксированной строки, БД может использовать B-tree индекс для быстрого поиска. Если шаблон начинается с % -- придётся сканировать всю таблицу.

-- быстро (index scan, если есть индекс на email)
WHERE email LIKE 'admin%'

-- медленно (full table scan)
WHERE email LIKE '%admin%'

Для полнотекстового поиска по %текст% на больших таблицах используйте:

  • GIN/GiST-индексы с pg_trgm в PostgreSQL
  • FULLTEXT-индексы в MySQL
  • Внешние движки поиска (Elasticsearch, Meilisearch)

ILIKE и LOWER() LIKE тоже не используют обычный B-tree индекс. В PostgreSQL для регистронезависимого поиска создайте индекс на LOWER(column) или используйте pg_trgm.

Практические примеры

Фильтрация email по домену:

SELECT user_id, email
FROM users
WHERE email LIKE '%@yandex.ru'

Поиск пользователей по началу имени:

SELECT user_id, name
FROM users
WHERE name ILIKE 'алекс%'
-- Александр, Алексей, Александра

Анализ UTM-меток:

SELECT
    utm_campaign,
    COUNT(*) AS visits
FROM onboarding_runs
WHERE utm_source LIKE 'tg_%'
GROUP BY utm_campaign
ORDER BY visits DESC

Чистка данных -- тестовые аккаунты:

DELETE FROM users
WHERE email LIKE '%+test%@%'
   OR email LIKE '%@test.%'

Типичные ошибки

Забыли % с нужной стороны. WHERE name LIKE 'Иван' -- это то же самое, что WHERE name = 'Иван'. Для поиска по подстроке нужен % с обеих сторон: LIKE '%Иван%'.

LIKE с числовыми столбцами. LIKE работает со строками. WHERE age LIKE '2%' может привести к неявному приведению типа или ошибке. Для чисел используйте диапазоны: WHERE age BETWEEN 20 AND 29.

Регистр. В PostgreSQL LIKE регистрозависим. 'Москва' LIKE '%москва%' вернёт FALSE. Используйте ILIKE или LOWER().

Шаблон % в начале на большой таблице. WHERE column LIKE '%value%' на таблице с миллионами строк без специального индекса -- это full scan. Если запрос тормозит, проверьте план через EXPLAIN.

Вопросы с собеседований

-- Чем отличается % от _ в LIKE? -- % соответствует любому количеству символов (включая ноль), _ -- ровно одному символу. LIKE 'A%' найдёт 'A', 'Ab', 'Abc'. LIKE 'A_' найдёт только строки из двух символов, начинающиеся на A.

-- Как сделать регистронезависимый поиск по шаблону в PostgreSQL? -- Использовать ILIKE вместо LIKE, либо привести обе стороны к одному регистру: WHERE LOWER(name) LIKE LOWER('%anna%'). ILIKE -- идиоматический вариант для PostgreSQL.

-- Будет ли использоваться индекс для WHERE email LIKE '%gmail.com'? -- Нет. Шаблон начинается с %, поэтому B-tree индекс не поможет -- БД выполнит full table scan. Индекс используется только когда шаблон начинается с фиксированной строки: LIKE 'admin%'.

-- Как найти строки, содержащие символ % в данных? -- Использовать ESCAPE: WHERE column LIKE '%100\%%' ESCAPE '\'. Здесь \% -- литеральный символ процента.

-- Напишите запрос: найти всех пользователей, чьё имя начинается на 'А' и содержит ровно 5 букв. -- SELECT * FROM users WHERE name LIKE 'А____'. Один символ А и четыре подчёркивания _ -- итого 5 символов.


Потренируйтесь решать задачи — откройте тренажёр с 1500+ вопросами для подготовки к собеседованиям аналитиков.

FAQ

Чем LIKE отличается от =?

= проверяет точное совпадение. LIKE позволяет использовать шаблоны % и _. WHERE name = 'Иван' найдёт только 'Иван', а WHERE name LIKE 'Иван%' -- также 'Иванов', 'Иванова' и т.д. Если шаблон не содержит спецсимволов, LIKE работает как =, но чуть медленнее.

Работает ли LIKE с NULL?

Нет. Любое сравнение с NULL даёт NULL, не TRUE и не FALSE. WHERE name LIKE '%test%' не вернёт строки, где name равен NULL. Если нужно обработать NULL -- добавьте отдельное условие: WHERE name LIKE '%test%' OR name IS NULL.

Когда использовать LIKE, а когда -- регулярные выражения?

LIKE достаточен для простых шаблонов: начинается с, заканчивается на, содержит подстроку. Для сложных паттернов (альтернативы, классы символов, повторения) используйте ~ в PostgreSQL или REGEXP в MySQL. LIKE быстрее и проще в чтении -- начинайте с него.

Поддерживается ли ILIKE во всех СУБД?

Нет. ILIKE -- расширение PostgreSQL. В MySQL LIKE по умолчанию регистронезависим. В SQL Server поведение зависит от collation. В стандартном SQL регистронезависимый поиск делается через LOWER(): WHERE LOWER(column) LIKE LOWER('%pattern%').

Как тренироваться

LIKE -- один из первых операторов, которые спрашивают на собеседовании по SQL. В тренажёре Карьерник есть задачи на фильтрацию строк по шаблону, работу с % и _, и регистронезависимый поиск. Также полезно разобрать CASE WHEN -- часто используется вместе с LIKE для условной логики.

Больше вопросов по SQL -- в примерах вопросов по всем темам.