Logika trójwartościowa i UNKNOWN
Dlaczego NULL = NULL nie jest prawdą i jak UNKNOWN propaguje się przez warunki
Logika trójwartościowa i UNKNOWN to bezpłatna lekcja SQL Interview Prep na CoddyKit. To lekcja 1 z 4. Możesz przeczytać całą lekcję poniżej za darmo — a potem ćwiczyć ją interaktywnie w przeglądarce z wbudowanym edytorem kodu i tutorem AI dostępnym 24/7. To część ścieżki edukacyjnej SQL Interview Prep, a Twój postęp synchronizuje się między webem a aplikacją CoddyKit. Kurs SQL Interview Prep zawiera 4 lekcji w sumie.
Dlaczego NULL sprawia kandydatom problemy
NULL jest najczęstszym źródłem błędnych odpowiedzi podczas rozmów technicznych dotyczących SQL. Pułapka polega na traktowaniu go jak zwykłej wartości, podczas gdy w rzeczywistości NULL oznacza „nieznaną” lub „brakującą” wartość, a nie zero ani pusty ciąg znaków.
Osoby rekrutujące często wykorzystują ten temat, ponieważ składnia wygląda poprawnie, ale wynik jest po cichu błędny. Mogą pokazać filtr, który „powinien” zwrócić wiersz, i zapytać, dlaczego nie zwraca niczego.
W tej lekcji zbudują Państwo model myślowy, który pozwala rozwiązać każde pytanie dotyczące NULL: logikę trójwartościową. Gdy zrozumieją Państwo, że porównania mogą zwracać TRUE, FALSE lub UNKNOWN, reszta stanie się oczywista.
NULL nie jest wartością
Najważniejsze zdanie, które warto wypowiedzieć podczas rozmowy: NULL oznacza brak wartości, a nie jest wartością samą w sobie.
Oznacza to, że nie można porównywać go za pomocą = tak jak liczb. Baza danych nie wie, czy dwie nieznane wartości są równe, więc nie rozstrzyga, czy wynikiem jest TRUE, czy FALSE.
NULL = 5to nie FALSE, lecz UNKNOWNNULL = NULLto nie TRUE, lecz UNKNOWNNULL <> NULLrównież daje UNKNOWN
Dlatego naiwny filtr równości zastosowany do kolumny dopuszczającej NULL po cichu pomija wiersze.
Logika dwuwartościowa a trójwartościowa
Większość języków programowania używa logiki dwuwartościowej: wyrażenie ma wartość TRUE albo FALSE. SQL dodaje trzeci wynik, UNKNOWN, gdy w porównaniu uczestniczy NULL.
Każdy predykat w SQL może więc przyjąć jeden z trzech wyników: TRUE, FALSE lub UNKNOWN. Klauzula WHERE zachowuje wiersz tylko wtedy, gdy predykat ma dokładnie wartość TRUE. Podczas filtrowania UNKNOWN zachowuje się jak FALSE, ale z punktu widzenia logiki nie jest tym samym.
Podczas rozmów rekrutacyjnych sprawdza się znajomość tego rozróżnienia, ponieważ UNKNOWN zachowuje się inaczej w połączeniu z NOT niż FALSE.
Filtr, który po cichu odrzuca wiersze
Oto klasyczny przykład. Załóżmy, że bonus ma czasami wartość NULL. Rekruter pyta: „To zapytanie powinno zwrócić wszystkich, których premia nie wynosi 1000. Dlaczego pomija pracowników bez premii?”
Dla wiersza, w którym bonus ma wartość NULL, wyrażenie bonus <> 1000 daje UNKNOWN, a nie TRUE. WHERE zachowuje wyłącznie wiersze z wynikiem TRUE, więc ci pracownicy znikają.
Rozwiązaniem jest jawne uwzględnienie NULL, czym zajmiemy się w następnej lekcji. Na razie proszę zapamiętać, że brakujące wiersze wynikają z logiki, a nie z błędu.
SELECT name, bonus
FROM employees
WHERE bonus <> 1000;
-- Rows where bonus IS NULL are excluded:
-- NULL <> 1000 evaluates to UNKNOWN, not TRUENULL w wyrażeniach AND
Logika trójwartościowa zmienia sposób działania AND. Proszę zapamiętać tę regułę, a będą Państwo w stanie od razu odpowiedzieć na każde pytanie dotyczące tabeli prawdy.
- TRUE AND UNKNOWN = UNKNOWN
- FALSE AND UNKNOWN = FALSE
- UNKNOWN AND UNKNOWN = UNKNOWN
Intuicja jest następująca: AND potrzebuje tylko jednego FALSE, aby wynik był bezdyskusyjnie FALSE. Dlatego FALSE AND cokolwiek nadal daje FALSE. Natomiast TRUE AND wartość nieznana wciąż daje wynik nieznany, ponieważ nieznana strona może ostatecznie przyjąć dowolną wartość.
-- If status = 'active' is TRUE but bonus = 100 is UNKNOWN:
SELECT *
FROM employees
WHERE status = 'active' AND bonus = 100;
-- Combined result is UNKNOWN, so the row is NOT returnedNULL w wyrażeniach OR
OR działa odwrotnie niż AND. Potrzebuje tylko jednego TRUE, aby wynik był bezdyskusyjnie TRUE, więc TRUE przesłania wartość nieznaną.
- TRUE OR UNKNOWN = TRUE
- FALSE OR UNKNOWN = UNKNOWN
- UNKNOWN OR UNKNOWN = UNKNOWN
Wiersz może więc nadal spełniać warunek OR, nawet gdy jedna gałąź ma nieznany wynik, o ile inna gałąź rzeczywiście daje TRUE. To częste pytanie uzupełniające po omówieniu AND.
SELECT *
FROM employees
WHERE department = 'Sales' OR bonus = 100;
-- A Sales employee with NULL bonus:
-- TRUE OR UNKNOWN = TRUE, so the row IS returnedNOT odwraca TRUE/FALSE, ale nie UNKNOWN
To subtelny przypadek, który osoby rekrutujące często zostawiają na koniec. NOT zamienia TRUE na FALSE, a FALSE na TRUE, ale NOT UNKNOWN nadal pozostaje UNKNOWN.
Dlatego nie można po prostu opakować nieskutecznego warunku w NOT, aby odwrócić wynik. Jeśli dla wiersza z wartością NULL wyrażenie bonus = 1000 daje UNKNOWN, to NOT (bonus = 1000) również daje UNKNOWN, a wiersz nadal zostaje wykluczony.
Negacja nie przywraca wierszy zawierających NULL. Służy do tego wyłącznie jawny test IS NULL.
-- For a row where bonus IS NULL:
-- bonus = 1000 -> UNKNOWN
-- NOT (bonus = 1000) -> UNKNOWN (still excluded)
SELECT * FROM employees WHERE NOT (bonus = 1000);Przykład: pułapka NOT IN
To jedna z najczęściej zadawanych zagadek dotyczących NULL. NOT IN z listą zawierającą NULL nie zwraca żadnych wierszy, co zaskakuje osoby, które oczekują, że NULL zostanie po prostu pominięty.
Wewnętrznie x NOT IN (1, 2, NULL) rozwija się do x <> 1 AND x <> 2 AND x <> NULL. To ostatnie porównanie daje UNKNOWN, a TRUE AND TRUE AND UNKNOWN sprowadza się do UNKNOWN, więc nic nie spełnia warunku.
Bezpieczną alternatywą jest NOT EXISTS, którego ten problem nie dotyczy.
-- Returns ZERO rows if the subquery yields any NULL
SELECT name
FROM employees
WHERE manager_id NOT IN (SELECT manager_id FROM managers);
-- Each comparison against NULL becomes UNKNOWN,
-- and the AND-chain collapses to UNKNOWN for every row.Dlaczego UNKNOWN zachowuje się jak FALSE w WHERE
Częste pytanie uzupełniające brzmi: „Jeśli UNKNOWN nie jest FALSE, dlaczego wiersz zostaje odrzucony tak jak wiersz z wynikiem FALSE?”
Odpowiedź jest precyzyjna: WHERE, ON i HAVING stosują zasadę zachowywania wyłącznie TRUE. Zarówno FALSE, jak i UNKNOWN nie spełniają tego warunku, więc podczas filtrowania wyglądają tak samo.
Różnica ujawnia się dopiero przy negacji i ograniczeniach CHECK. Ograniczenie CHECK przepuszcza wiersz, gdy warunek ma wartość TRUE lub UNKNOWN, więc NULL może przejść przez CHECK, które miało go zablokować.
-- CHECK passes on TRUE or UNKNOWN, so NULL salary is allowed:
-- CONSTRAINT salary_positive CHECK (salary > 0)
-- INSERT ... salary = NULL -> NULL > 0 is UNKNOWN -> allowedGłębszy przykład: COUNT i luka w logice trójwartościowej
Połączmy te zasady w realistycznym pytaniu rekrutacyjnym: „Mamy 100 pracowników. SELECT COUNT(*) WHERE bonus = 100 zwraca 30, a WHERE bonus <> 100 zwraca 50. Gdzie jest pozostałych 20?”
Brakujące 20 osób ma NULL w kolumnie bonus. Ani = 100, ani <> 100 nie daje dla nich TRUE — oba wyrażenia dają UNKNOWN, więc te osoby wypadają z obu filtrów.
Zdanie „koszyki nie sumują się do całości, ponieważ NULL nie spełnia żadnego z predykatów” jest dokładnie odpowiedzią, której oczekują osoby rekrutujące.
SELECT
COUNT(*) FILTER (WHERE bonus = 100) AS eq_100,
COUNT(*) FILTER (WHERE bonus <> 100) AS ne_100,
COUNT(*) FILTER (WHERE bonus IS NULL) AS null_bonus,
COUNT(*) AS total
FROM employees;Najważniejsze punkty na rozmowie
Gdy pojawi się temat logiki NULL, proszę poruszyć następujące kwestie, aby zaprezentować zaawansowane rozumienie tematu:
- NULL oznacza UNKNOWN; porównania z NULL dają UNKNOWN.
- SQL używa logiki trójwartościowej: TRUE, FALSE, UNKNOWN.
- WHERE, ON i HAVING zachowują wyłącznie wiersze z wynikiem TRUE.
NOT UNKNOWNnadal daje UNKNOWN, więc negacja nie przywraca wierszy zawierających NULL.NOT INz dowolną wartością NULL nie zwraca żadnych wierszy; preferujNOT EXISTS.
Najpierw proszę przedstawić model, a dopiero potem przejść przez tabelę prawdy. Taka kolejność pokazuje, że rozumieją Państwo nie tylko sztuczkę, ale także jej przyczynę.
Szybki test
Proszę sprawdzić swoją znajomość logiki trójwartościowej.
Podsumowanie
Znają już Państwo podstawowy model myślowy dotyczący NULL:
- NULL oznacza UNKNOWN, a nie wartość; nigdy nie porównuj go za pomocą
=ani<>. - SQL jest trójwartościowy: predykaty zwracają TRUE, FALSE lub UNKNOWN.
- Klauzule filtrujące zachowują wyłącznie TRUE; wiersze z UNKNOWN znikają tak samo jak wiersze z FALSE.
NOTodwraca TRUE i FALSE, ale pozostawia UNKNOWN bez zmian.- Pułapka
NOT IN+ NULL zwraca zero wierszy; należy użyćNOT EXISTS.
W następnej części: prawidłowy sposób sprawdzania NULL za pomocą IS NULL, IS NOT NULL oraz operatorów porównania bezpiecznych względem NULL.
Często zadawane pytania
Czy lekcja „Logika trójwartościowa i UNKNOWN” jest bezpłatna?
Tak — pełny tekst „Logika trójwartościowa i UNKNOWN” jest dostępny za darmo tutaj w sieci. Aby ćwiczyć ją interaktywnie (wbudowany edytor kodu i tutor AI dostępny 24/7) i odblokować resztę kursu SQL Interview Prep, przejdź na CoddyKit PRO. Kurs SQL Interview Prep zawiera 4 lekcji w sumie.
Co nauczysz się w „Logika trójwartościowa i UNKNOWN”?
Dlaczego NULL = NULL nie jest prawdą i jak UNKNOWN propaguje się przez warunki Ćwiczysz SQL Interview Prep z praktycznym kodem, który uruchamiasz bezpośrednio w przeglądarce, a tutor AI dostępny 24/7 odpowiada na Twoje pytania podczas pracy nad lekcją.
Czy potrzebuję doświadczenia, aby zacząć SQL Interview Prep?
Nie wymagamy żadnego doświadczenia. SQL Interview Prep w CoddyKit jest strukturyzowany dla początkujących i zaawansowanych użytkowników, więc możesz zacząć tutaj lub od początku i uczyć się w swoim tempie. To lekcja 1 z 4.
Ile czasu zajmuje lekcja „Logika trójwartościowa i UNKNOWN”?
Większość lekcji CoddyKit trwa około 5–10 minut. Każda lekcja to mały, interaktywny krok, dzięki czemu robisz systematyczne postępy i zawsze wracasz dokładnie do tego samego miejsca — na webie i w aplikacji.
Czy mogę pisać i uruchamiać kod w tej lekcji SQL Interview Prep?
Tak. Każda lekcja SQL Interview Prep zawiera wbudowany edytor kodu, więc piszesz i uruchamiasz prawdziwy kod bezpośrednio w przeglądarce i od razu otrzymujesz sprzężenie zwrotne od AI — bez konfiguracji na komputerze.
Wszystkie lekcje w tym kursie
- Logika trójwartościowa i UNKNOWN
- IS NULL, IS NOT NULL i porównywanie bezpieczne dla NULL
- COALESCE, NULLIF i ISNULL
- Wartości NULL w agregatach, złączeniach i DISTINCT