0Pricing
SQL Interview Prep · Lekcja

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 = 5 to nie FALSE, lecz UNKNOWN
  • NULL = NULL to nie TRUE, lecz UNKNOWN
  • NULL <> NULL ró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 TRUE

NULL 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 returned

NULL 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 returned

NOT 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 -> allowed

Głę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 UNKNOWN nadal daje UNKNOWN, więc negacja nie przywraca wierszy zawierających NULL.
  • NOT IN z dowolną wartością NULL nie zwraca żadnych wierszy; preferuj NOT 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.
  • NOT odwraca 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

  1. Logika trójwartościowa i UNKNOWN
  2. IS NULL, IS NOT NULL i porównywanie bezpieczne dla NULL
  3. COALESCE, NULLIF i ISNULL
  4. Wartości NULL w agregatach, złączeniach i DISTINCT
← Powrót do SQL Interview Prep