WHERE filtruje wiersze po kolei
SELECT bez WHERE zwraca każdy wiersz tabeli. Rzadko o to chodzi. WHERE pozwala zostawić tylko wiersze spełniające warunek: SQLite przechodzi przez tabelę, sprawdza warunek dla każdego wiersza i zostawia te, dla których jest prawdziwy.
Wracają trzy wiersze: Neuromancer, Hyperion i The Martian. Warunek year > 1980 został sprawdzony dla każdego wiersza i przetrwały tylko te pasujące.
Model myślowy: WHERE to filtr między FROM a wybieranymi kolumnami. Przechodzi przez niego wszystko, co daje prawdę.
Operatory porównania
Podstawy działają tak, jak się spodziewasz:
= oznacza równość, != albo <> oznacza „różne od”, a <, <=, >, >= służą do porównań kolejności. Napisy porównuje się tymi samymi operatorami: author = 'Asimov' pasuje dokładnie, znak po znaku.
Jedna rzecz, o której warto wiedzieć: SQL używa pojedynczych cudzysłowów dla literałów tekstowych. Podwójne cudzysłowy są dla identyfikatorów (nazw kolumn lub tabel). WHERE author = "Asimov" może w SQLite działać z powodów historycznych, ale nie jest przenośne i może po cichu działać źle, gdy „napis” akurat pasuje do nazwy kolumny. Trzymaj się pojedynczych cudzysłowów.
AND, OR i nawiasy
Prawdziwe zapytania zwykle łączą warunki. AND wymaga, żeby obie strony były prawdziwe; OR wymaga co najmniej jednej:
Pierwsze zapytanie wybiera książki nowe i krótkie. Drugie pobiera książki któregokolwiek z dwóch autorów.
Gdy mieszasz AND i OR, kolejność działań daje w kość. AND wiąże silniej niż OR, więc:
czyta się jako Herbert OR (Gibson AND year > 1980): każda książka Herberta niezależnie od roku, plus książki Gibsona po 1980. Pewnie nie o to chodziło. Zapisz swój zamiar w nawiasach:
W razie wątpliwości dodaj nawiasy. Optymalizatorowi zapytań to obojętne, a następna osoba, która to przeczyta, będzie ci wdzięczna.
NULL nie zachowuje się jak wartość
To pułapka klauzuli WHERE, na którą każdy raz się złapie. NULL w SQL oznacza „nieznane”, a nieznanych wartości nie da się porównywać. column = NULL nie jest fałszem: to NULL, które WHERE traktuje jako „pomiń ten wiersz”.
IS NULL i IS NOT NULL to jedyne operatory, które bezpośrednio sprawdzają NULL. Wbij je sobie w palce: każde inne porównanie z NULL zwraca NULL i po cichu odrzuca wiersze.
Ta sama zasada dotyczy negacji. WHERE author != 'Asimov' nie zwraca wierszy, w których author IS NULL, bo NULL != 'Asimov' to też NULL. Jeśli chcesz uwzględnić NULL, poproś o nie jawnie: WHERE author != 'Asimov' OR author IS NULL.
IN i BETWEEN: skróty na co dzień
IN sprawdza przynależność do listy. To czytelniejszy sposób na zapisanie łańcucha OR:
BETWEEN sprawdza zakres, włącznie z oboma końcami:
year BETWEEN 1980 AND 2000 jest identyczne z year >= 1980 AND year <= 2000, tylko krótsze. Pamiętaj: obie granice są włączone. Jeśli chcesz granic wyłącznych, rozpisz porównania.
Krótka uwaga o IN i NULL: WHERE column NOT IN (1, 2, NULL) nigdy nie zwróci żadnego wiersza, bo porównanie czegokolwiek z NULL daje NULL. Usuń NULL z listy albo obsłuż je osobno przez IS NULL.
LIKE do dopasowywania wzorców
LIKE dopasowuje wzorce tekstowe z dwoma symbolami wieloznacznymi:
%pasuje do dowolnego ciągu znaków (także pustego)._pasuje do dokładnie jednego znaku.
Domyślnie LIKE w SQLite nie rozróżnia wielkości liter ASCII: 'Dune' LIKE 'dune' jest prawdą. To zaskakuje osoby przychodzące z Postgresa, gdzie LIKE rozróżnia wielkość liter, a ILIKE to wersja bez rozróżniania. (SQLite nie ma ILIKE.)
Jeśli potrzebujesz dopasowania z rozróżnianiem wielkości liter, masz dwie opcje. Przełącz globalną pragmę:
PRAGMA case_sensitive_like = ON;
Albo użyj GLOB, który zawsze rozróżnia wielkość liter i korzysta z symboli wieloznacznych w stylu Unix (* dla dowolnego ciągu, ? dla jednego znaku):
GLOB 'd*' nie dopasowałby tu niczego: wielkość liter ma znaczenie.
Filtrowanie dat
SQLite przechowuje daty jako tekst (zwykle YYYY-MM-DD albo pełne ISO 8601), więc porównania napisów działają przy okazji jako porównania dat, o ile trzymasz się formatu ISO:
Ponieważ '2024-06-01' < '2024-11-08' jest prawdą zarówno dla napisów, jak i dla dat, te zapytania robią to, czego się spodziewasz. Jeśli przechowujesz daty w innym formacie ('15/01/2024', 'Jan 15 2024'), porównania po cichu dadzą błędne wyniki. Zawsze używaj ISO 8601, a w przyszłości sobie za to podziękujesz.
Do trudniejszych obliczeń na datach (wyciąganie roku, porównanie z „dzisiaj”) SQLite ma funkcje date(), strftime() i julianday(). Omawiamy je w rozdziale o dacie i czasie.
Wszystko razem
Zapytanie, które używa kilku z tych elementów naraz:
Czytaj je linijka po linijce: zostaw wiersze ze znanym rokiem, w zakresie, jednego z dwóch autorów albo wystarczająco długie, i nie szkice. To klauzula WHERE w najlepszym wydaniu: łączy małe, czytelne warunki w precyzyjne filtry.
Dwa nawyki, które warto zachować:
- Każdy warunek pisz w osobnej linii z wcięciem. Długie klauzule
WHEREzapisane w jednej ogromnej linii szybko stają się nieczytelne. - Komentuj intencję tam, gdzie warunek nie jest oczywisty.
-- pomiń szkiceto tanie ubezpieczenie.
Dalej: operatory i NULL w szczegółach
Klauzula WHERE to głównie operatory zastosowane do kolumn, a NULL po cichu zmienia działanie każdego z nich. Następna strona wchodzi głębiej w zestaw operatorów SQLite: arytmetykę, łączenie napisów przez ||, rodzinę IS i logikę trójwartościową, żeby niespodzianki przestały być niespodziankami.
Najczęściej zadawane pytania
Jak działa klauzula WHERE w SQLite?
WHERE filtruje wiersze zapytania, sprawdzając warunek dla każdego wiersza. Wiersze, dla których warunek jest prawdziwy, zostają; te, dla których jest fałszywy albo NULL, są odrzucane. Klauzula stoi zaraz po FROM: SELECT ... FROM table WHERE condition.
Jak połączyć kilka warunków w klauzuli WHERE w SQLite?
Użyj AND i OR. AND wymaga, żeby obie strony były prawdziwe; OR potrzebuje tylko jednej. AND wiąże silniej niż OR, więc mieszane warunki ujmuj w nawiasy, żeby zapis był jednoznaczny: WHERE (a OR b) AND c.
Dlaczego WHERE column = NULL nie działa w SQLite?
NULL oznacza „nieznane”, więc każde porównanie przez = albo != zwraca NULL zamiast prawdy lub fałszu, a wiersze zostają tylko wtedy, gdy warunek jest prawdziwy. Zamiast tego używaj IS NULL i IS NOT NULL. To jedyne operatory, które bezpośrednio sprawdzają NULL.
Czy LIKE w klauzuli WHERE w SQLite rozróżnia wielkość liter?
Domyślnie LIKE nie rozróżnia wielkości liter dla znaków ASCII: 'Hello' LIKE 'hello' jest prawdą. Aby w pełni rozróżniać wielkość liter, ustaw PRAGMA case_sensitive_like = ON; albo użyj GLOB, który zawsze rozróżnia wielkość liter i korzysta z symboli wieloznacznych w stylu Unix (* i ?).