WHERE: фильтруем строки по условию
SELECT без WHERE возвращает все строки таблицы — а это редко то, что нужно на практике. Условие WHERE в SQLite оставляет только те строки, которые подходят под заданное условие: SQLite проходит по таблице, проверяет условие для каждой строки и отбирает те, где оно истинно.
В ответе приходят три строки: Neuromancer, Hyperion и The Martian. Условие year > 1980 проверилось для каждой строки, и наружу попали только те, что ему соответствуют.
Удобная мысленная модель: WHERE — это фильтр, который стоит между FROM и списком выбираемых колонок. Всё, что даёт в результате истину, проходит дальше.
Операторы сравнения в sqlite where
Базовые операторы работают ровно так, как вы и ожидаете:
= для равенства, != или <> для «не равно», а также <, <=, >, >= для сравнения по порядку. Со строками работают те же операторы — author = 'Asimov' находит точное совпадение, символ в символ.
Один важный момент: в SQL одинарные кавычки используются для строковых литералов, а двойные — для идентификаторов (имён столбцов или таблиц). Запрос WHERE author = "Asimov" в SQLite может сработать по историческим причинам, но это не переносимо между СУБД и способно тихо ломаться, если «строка» вдруг совпадёт с названием столбца. Лучше всегда использовать одинарные кавычки.
Несколько условий в SQLite WHERE: AND, OR и скобки
В реальных запросах условия почти всегда комбинируются. AND требует, чтобы обе стороны были истинны, а OR — чтобы выполнилась хотя бы одна:
Первый запрос отбирает свежие и короткие книги. Второй вытаскивает книги любого из двух авторов.
Когда в одном WHERE намешаны AND и OR, легко напороться на приоритет операторов. AND связывает сильнее, чем OR, поэтому:
читается как Herbert OR (Gibson AND year > 1980) — то есть все книги Herbert независимо от года плюс книги Gibson после 1980-го. Скорее всего, вы имели в виду совсем не это. Оборачивайте логику в скобки явно:
Если сомневаешься — ставь скобки. Оптимизатору запросов всё равно, а тот, кто будет читать твой код потом, скажет тебе спасибо.
NULL ведёт себя не как обычное значение
Это та самая ловушка в WHERE, в которую хоть раз попадает каждый. NULL в SQL означает «неизвестно», а неизвестное нельзя ни с чем сравнить. Запись column = NULL — это не ложь, это NULL, и WHERE воспринимает такой результат как «пропустить строку».
IS NULL и IS NOT NULL — единственные операторы, которые умеют проверять NULL напрямую. Вбейте это себе в пальцы: любое другое сравнение с NULL возвращает NULL и тихо выбрасывает строку из результата.
С отрицанием та же история. WHERE author != 'Asimov' не вернёт строки, где author IS NULL, потому что NULL != 'Asimov' — это тоже NULL. Хотите видеть NULL-ы в выдаче — пропишите это явно: WHERE author != 'Asimov' OR author IS NULL.
sqlite where in и between: операторы на каждый день
IN проверяет, входит ли значение в список. По сути — это аккуратная замена цепочке OR:
BETWEEN проверяет попадание в диапазон, причём включая обе границы:
year BETWEEN 1980 AND 2000 — это то же самое, что и year >= 1980 AND year <= 2000, только короче. Важный момент: обе границы включаются. Если нужны строгие границы — пишите сравнения вручную.
Пара слов про IN и NULL: запрос WHERE column NOT IN (1, 2, NULL) никогда не вернёт ни одной строки, потому что любое сравнение с NULL даёт NULL. Либо убирайте NULL из списка заранее, либо обрабатывайте его отдельно через IS NULL.
LIKE: поиск по шаблону в SQLite
Оператор LIKE сравнивает строки по шаблону и поддерживает два подстановочных символа:
%— любая последовательность символов (в том числе пустая)._— ровно один любой символ.
По умолчанию оператор LIKE в SQLite не различает регистр для ASCII-букв — выражение 'Dune' LIKE 'dune' вернёт истину. Это неожиданно для тех, кто пришёл из Postgres, где LIKE чувствителен к регистру, а его регистронезависимый аналог — ILIKE. (В SQLite никакого ILIKE нет.)
Если же вам нужно точное совпадение с учётом регистра, есть два пути. Первый — переключить глобальную прагму:
PRAGMA case_sensitive_like = ON;
Либо используйте GLOB — он всегда чувствителен к регистру и работает с Unix-подобными шаблонами (* — любая последовательность символов, ? — ровно один символ):
GLOB 'd*' тут не найдёт ничего — регистр имеет значение.
Фильтрация по датам
В SQLite даты хранятся как текст (обычно YYYY-MM-DD или полный ISO 8601), и благодаря этому сравнение строк одновременно работает как сравнение дат — главное, придерживаться формата ISO:
Так как '2024-06-01' < '2024-11-08' истинно и для строк, и для дат, такие запросы отрабатывают как надо. Но стоит сохранить даты в каком-нибудь другом виде ('15/01/2024', 'Jan 15 2024') — и сравнения молча начнут выдавать неверные результаты. Всегда придерживайтесь ISO 8601, потом сами себе скажете спасибо.
Для более хитрых вычислений с датами (вытащить год, сравнить с «сегодня») в SQLite есть функции date(), strftime() и julianday(). Разберём их в главе про дату и время.
Собираем всё вместе: WHERE с несколькими условиями
Запрос, в котором сразу используется несколько приёмов:
Читай построчно: оставляем строки, где год известен, попадает в диапазон, автор — один из двух или текст достаточно длинный, и при этом запись не черновик. Вот это и есть WHERE в своей стихии — собирать маленькие, читаемые условия в точный фильтр.
Пара привычек, которые стоит закрепить:
- Каждое условие — на отдельной строке с отступом. Длинный
WHERE, размазанный в одну строку, читать невозможно. - Комментируй намерение там, где условие неочевидно.
-- исключаем черновики— дешёвая страховка от будущих вопросов «а это вообще зачем?».
Что дальше: операторы и NULL во всех подробностях
WHERE в основном состоит из операторов, применённых к столбцам, а NULL тихо меняет поведение каждого из них. На следующей странице копнём глубже в набор операторов SQLite — арифметика, конкатенация строк через ||, семейство IS, трёхзначная логика — чтобы сюрпризы перестали быть сюрпризами.
Часто задаваемые вопросы
Как работает WHERE в SQLite?
WHERE отбирает строки запроса, проверяя условие для каждой из них. Если условие истинно — строка попадает в результат, если ложно или равно NULL — отбрасывается. Пишется сразу после FROM: SELECT ... FROM table WHERE условие.
Как объединить несколько условий в WHERE?
Через AND и OR. AND требует, чтобы оба условия были истинны, а OR — хотя бы одно. У AND приоритет выше, чем у OR, поэтому при смешанных условиях лучше явно расставлять скобки: WHERE (a OR b) AND c.
Почему WHERE column = NULL не работает?
NULL — это "неизвестно", поэтому любое сравнение через = или != возвращает не true и не false, а тот же NULL. А строки попадают в выборку только при истинном условии. Для проверки используйте IS NULL и IS NOT NULL — это единственные операторы, которые корректно работают с NULL.
Чувствителен ли LIKE в SQLite к регистру?
По умолчанию LIKE нечувствителен к регистру для ASCII-символов — 'Hello' LIKE 'hello' вернёт true. Если нужно строгое сравнение по регистру, включите PRAGMA case_sensitive_like = ON; или используйте GLOB — он всегда учитывает регистр и работает с шаблонами в Unix-стиле (* и ?).