Wróć do: Bazy danych
średni SQLNULLIS NULLmatura rozszerzona z informatyki

NULL – wartości puste

Czym jest NULL, dlaczego nie da się go porównać znakiem równości i jak wyszukiwać brakujące dane operatorami IS NULL oraz IS NOT NULL.

01

Opis

NULL oznacza brak wartości – informację, której w bazie nie ma. To nie to samo co zero i nie to samo co pusty tekst. Zero to konkretna liczba, pusty tekst to konkretny (choć zerowej długości) napis, a NULL to znacznik mówiący „tego pola nikt nie wypełnił".

Z tego jednego faktu wynika cała reszta. Skoro w polu nic nie ma, to nie da się go z niczym porównać. Pytanie „czy ta pusta wartość równa się 5" nie może dać odpowiedzi „tak" ani „nie" – jedyną uczciwą odpowiedzią jest „nie wiadomo".

Dlatego = NULL nigdy nie zadziała. I to jest najważniejsze zdanie w tym haśle: warunek WHERE email = NULL nie zgłosi błędu, tylko zwróci pustą tabelę. Zawsze, dla każdych danych. Bo porównanie z pustym polem nie daje ani prawdy, ani fałszu, a WHERE przepuszcza wyłącznie wiersze, dla których warunek wyszedł prawdziwy.

Z tego samego powodu NULL <> NULL też nie jest prawdą. Dwa puste pola nie są sobie ani równe, ani różne – nie wiadomo, co miało w nich być, więc nie wiadomo, jak się mają do siebie.

Do szukania braków służą osobne operatory: IS NULL sprawdza, czy wartości brakuje, a IS NOT NULL – czy jest obecna. To jedyny poprawny sposób i jedyny, który działa.

Logika trójwartościowa. Warunek w SQL-u nie ma dwóch możliwych wyników, tylko trzy: prawda, fałsz i nieznane.

Tu potrzebne jest rozróżnienie, które łatwo przeoczyć, a bez którego reszta się rozmywa. NULL to brak wartości w kolumnie – coś, co leży w tabeli. „nieznane" to wynik warunku – to, co wychodzi ze sprawdzenia, a nie to, co jest w komórce. Łączy je jedno: warunek dotyczący pola z NULL-em daje w wyniku „nieznane". W anglojęzycznych materiałach ta trzecia wartość nazywa się UNKNOWN i nigdy nie jest nazywana NULL.

Wynika stąd zachowanie, które na pierwszy rzut oka zaskakuje, a po chwili jest oczywiste: warunek nieznany połączony przez AND z fałszywym daje fałsz (skoro drugi człon jest fałszywy, całość jest fałszywa niezależnie od pierwszego), ale połączony z prawdziwym daje nieznane. Podobnie warunek nieznany połączony przez OR z prawdziwym daje prawdę, bo do spełnienia OR wystarczy jeden człon.

NULL cicho wypada z wyników. Jeśli filtrujesz po kolumnie, w której są braki, wiersze z NULL nie trafią do wyniku ani przy warunku, ani przy jego zaprzeczeniu. Suma wyników zapytania i zapytania odwrotnego może więc być mniejsza niż liczba wierszy w tabeli – i nie jest to błąd. To najczęstsza przyczyna „gubiących się" wierszy.

Gdzie jeszcze NULL zmienia wynik:

Funkcje agregujące pomijają puste wartości – AVG liczy średnią z wierszy, które mają wartość, a nie traktuje braku jak zera. Wyjątkiem jest COUNT(*), który liczy wiersze, a nie wartości.

DISTINCT traktuje wszystkie NULL jak jedną wartość i zostawia z nich jeden wiersz – choć formalnie nie da się ich ze sobą porównać.

NOT IN potrafi zwrócić pustą tabelę, jeśli na liście po prawej stronie znajdzie się choć jeden NULL. To wprost konsekwencja tego, że porównanie z pustym polem nigdy nie wychodzi fałszywe – a NOT IN potrzebuje właśnie fałszu, żeby wiersz przepuścić.

Złączenie wewnętrzne pomija wiersze bez dopasowania – ale to inne zjawisko niż NULL: tam wiersza po prostu nie ma, a tu wiersz jest, tylko jedna jego kolumna jest pusta.

02

Tabela

W tabeli są WYNIKI WARUNKÓW, nie zawartość kolumn. „nieznane" to wynik warunku, w którym trafił się NULL – a nie sama wartość NULL
Wynik warunku AWynik warunku BA AND BA OR B
prawdaprawdaprawdaprawda
prawdafałszfałszprawda
fałszfałszfałszfałsz
prawdanieznanenieznaneprawda
fałsznieznanefałsznieznane
nieznanenieznanenieznanenieznane
03

Zapytanie

-- Poprawnie: operator IS NULL
SELECT nazwisko, email
FROM uczniowie
WHERE email IS NULL
Wynik zapytania
nazwiskoemail
Nowak
Zając
-- Błędnie: = NULL nie zgłasza błędu, tylko ZAWSZE zwraca pustą tabelę
SELECT nazwisko, email
FROM uczniowie
WHERE email = NULL
-- IS NOT NULL: wiersze, w których wartość jest obecna
SELECT nazwisko, email
FROM uczniowie
WHERE email IS NOT NULL
Wynik zapytania
nazwiskoemail
Kowalskaa.kowalska@example.com
Wiśniewskim.wisniewski@example.com
Dąbrowskik.dabrowski@example.com

Na maturze

Gdy zapytanie zwraca pustą tabelę bez powodu, sprawdź, czy nie porównujesz z NULL. To błąd bez komunikatu – składnia jest poprawna, więc nic nie sygnalizuje problemu. Objaw jest zawsze ten sam: zero wierszy przy danych, w których na oko coś powinno być.

Sprawdź, czy liczby się sumują. Jeśli zadanie dzieli tabelę na dwie grupy warunkiem i jego zaprzeczeniem, policz, czy obie części dają razem całą tabelę. Jeśli nie – w kolumnie warunku są puste wartości i trzeba je obsłużyć osobno przez IS NULL.

Nie myl braku wartości z brakiem wiersza. „Uczeń bez adresu e-mail" to wiersz z NULL w kolumnie – szukasz go przez IS NULL. „Uczeń bez ani jednej oceny" to brak wierszy w drugiej tabeli – szukasz go przez NOT IN z podzapytaniem albo złączenie zewnętrzne. To dwa różne pytania i dwa różne narzędzia.

Uważaj przy średnich. Średnia policzona przez bazę pomija braki, więc dzieli przez liczbę wypełnionych pól. Jeśli zadanie wymaga potraktowania braku jak zera, trzeba to zrobić jawnie – sama funkcja tego nie zrobi.

05

Najczęściej zadawane pytania

Czy „nieznane" to inna nazwa NULL-a?

Nie, to dwie różne rzeczy na dwóch różnych poziomach. NULL jest wartością (a dokładniej: jej brakiem) i siedzi w kolumnie tabeli. „nieznane" jest wynikiem warunku i stoi obok prawdy i fałszu w tabeli prawdy. W komórce tabeli nigdy nie zobaczysz „nieznane", a wynikiem warunku nigdy nie jest NULL. Powiązanie jest jednokierunkowe: gdy warunek dotyczy pola z NULL-em, jego wynikiem jest „nieznane".

Czy NULL to to samo co pusty tekst?

Nie. Pusty tekst jest konkretną wartością o zerowej długości – da się go znaleźć zwykłym porównaniem = ''. NULL to brak jakiejkolwiek wartości i wymaga IS NULL. W jednej kolumnie mogą występować oba naraz, co bywa źródłem trudnych do wykrycia pomyłek.

Czy da się napisać `IS NOT NULL` inaczej?

Część baz akceptuje NOT (kolumna IS NULL), co znaczy to samo. IS NOT NULL jest jednak krótsze i czytelniejsze, więc nie ma powodu, żeby pisać inaczej.

Co zwróci działanie arytmetyczne na NULL?

Również NULL. Dodanie czegokolwiek do pustego pola znów daje puste pole – więc srednia + 1 dla wiersza z pustą średnią nie da 1, tylko NULL. To samo dotyczy sklejania tekstów: dołączenie NULL do napisu potrafi wyzerować całe wyrażenie.

Powiązane zagadnienia