IS NULL, IS NOT NULL i porównywanie bezpieczne dla NULL
Poprawne testowanie wartości NULL oraz operatory bezpieczne dla NULL w poszczególnych dialektach
IS NULL, IS NOT NULL i porównywanie bezpieczne dla NULL to bezpłatna lekcja Coding Interview Prep na CoddyKit. To lekcja 2 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 Coding Interview Prep, a Twój postęp synchronizuje się między webem a aplikacją CoddyKit. Kurs Coding Interview Prep zawiera 4 lekcji w sumie.
Prawidłowe sprawdzanie NULL
W poprzedniej lekcji wykazaliśmy, że do wyszukiwania wartości NULL nie można używać =. Jak więc przeprowadzić takie sprawdzenie? Służą do tego dedykowane predykaty IS NULL i IS NOT NULL.
To jedyne poprawne i przenośne sposoby sprawdzania brakujących wartości, a osoby rekrutujące za każdym razem odrzucą zapis col = NULL.
W tej lekcji omówimy IS NULL, IS NOT NULL, rodzinę IS DISTINCT FROM oraz zależne od dialektu operatory porównania bezpiecznego względem NULL. Znajomość różnic między bazami danych jest mocnym sygnałem zaawansowanych umiejętności.
IS NULL i IS NOT NULL
IS NULL zwraca TRUE, gdy wartość jest NULL, a w przeciwnym razie FALSE. Co najważniejsze, nigdy nie zwraca UNKNOWN, więc można bezpiecznie używać go bezpośrednio w WHERE.
IS NOT NULL jest jego dokładnym dopełnieniem: zwraca TRUE dla każdej wartości innej niż NULL oraz FALSE dla NULL.
Predykaty te są podstawowymi narzędziami obsługi NULL. Stanowią standard SQL i działają identycznie w MySQL, Postgres, SQL Server, Oracle i SQLite.
-- Find employees with no recorded bonus
SELECT name FROM employees WHERE bonus IS NULL;
-- Find employees that do have a bonus
SELECT name FROM employees WHERE bonus IS NOT NULL;Dlaczego col = NULL jest zawsze błędne
To gwarantowana pułapka podczas rozmowy: kandydat zapisuje WHERE bonus = NULL, oczekując znalezienia brakujących premii. Zapytanie zwraca zero wierszy.
Proszę pamiętać o logice trójwartościowej: bonus = NULL daje UNKNOWN dla każdego wiersza, także dla wierszy zawierających NULL, ponieważ nic nie jest równe wartości nieznanej. WHERE zachowuje tylko TRUE, więc nic nie pasuje.
Niektóre bazy danych w niestandardowych trybach po cichu przepisują = NULL na IS NULL, ale nigdy nie należy na tym polegać. Zawsze proszę jawnie zapisywać IS NULL.
-- WRONG: returns zero rows, bonus = NULL is UNKNOWN for all
SELECT name FROM employees WHERE bonus = NULL;
-- RIGHT:
SELECT name FROM employees WHERE bonus IS NULL;Zliczanie wartości NULL i innych niż NULL
Częstym zadaniem analitycznym jest kontrola jakości danych: na ile kompletna jest kolumna? Połącz IS NULL z COUNT, aby raportować brakujące wartości.
Proszę zwrócić uwagę na różnicę: COUNT(*) zlicza każdy wiersz, natomiast COUNT(bonus) zlicza tylko premie inne niż NULL. Różnica między tymi wynikami jest równa liczbie wartości NULL — wrócimy do tego w lekcji dotyczącej agregacji.
SELECT
COUNT(*) AS total_rows,
COUNT(bonus) AS with_bonus,
COUNT(*) - COUNT(bonus) AS missing_bonus,
SUM(CASE WHEN bonus IS NULL THEN 1 ELSE 0 END) AS missing_check
FROM employees;Problem rozwiązywany przez porównanie NULL-safe
Załóżmy, że chcą Państwo porównać dwie kolumny, uznając „obie wartości NULL” za dopasowanie. Zwykłe a = b nie działa: gdy obie wartości są NULL, wynikiem jest UNKNOWN, więc para zostaje wykluczona, mimo że intuicyjnie są „takie same”.
Ten przypadek pojawia się przy porównywaniu starego wiersza z nowym w celu wykrycia zmian albo przy złączaniu po opcjonalnych kolumnach. Potrzebują Państwo porównania, w którym NULL = NULL daje TRUE, a NULL w porównaniu z wartością daje FALSE. To właśnie zapewnia porównanie bezpieczne względem NULL.
-- Goal: change-detection where two NULLs count as equal
-- Plain equality fails when both sides are NULL:
-- NULL = NULL -> UNKNOWN (treated as not-equal)
SELECT * FROM old_t o JOIN new_t n ON o.id = n.id
WHERE o.note = n.note; -- misses rows where both notes are NULLIS DISTINCT FROM (standard SQL)
Standardowym porównaniem bezpiecznym względem NULL jest IS DISTINCT FROM, a jego odwrotnością — IS NOT DISTINCT FROM. Operatory te są obsługiwane w Postgres, SQL Server (2022+) i innych bazach.
a IS NOT DISTINCT FROM boznacza „równe, przy czym NULL = NULL jest traktowane jako równość”.a IS DISTINCT FROM boznacza „różne, z traktowaniem NULL jak zwykłej wartości”.
Operatory te zawsze zwracają TRUE albo FALSE, nigdy UNKNOWN, więc można bezpiecznie używać ich wszędzie tam, gdzie oczekiwany jest predykat.
-- TRUE when notes match, including both NULL
SELECT * FROM old_t o JOIN new_t n ON o.id = n.id
WHERE o.note IS NOT DISTINCT FROM n.note;
-- TRUE when notes differ (NULL vs value counts as different)
SELECT * FROM old_t o JOIN new_t n ON o.id = n.id
WHERE o.note IS DISTINCT FROM n.note;Operator <=> w MySQL
MySQL udostępnia zwięzły operator porównania bezpiecznego względem NULL, zapisywany jako <=> — tak zwany operator spaceship.
a <=> b zwraca 1 (TRUE), gdy obie strony są równe albo obie są NULL, a w przeciwnym razie 0 (FALSE). Jest to odpowiednik IS NOT DISTINCT FROM w MySQL.
Jeśli podczas rozmowy rekrutacyjnej padnie pytanie o bezpieczne względem NULL dopasowanie konkretnie w MySQL, jest to idiomatyczna odpowiedź.
-- MySQL: 1 when both equal or both NULL
SELECT (NULL <=> NULL) AS both_null, -- 1
(NULL <=> 5) AS null_vs_val, -- 0
(5 <=> 5) AS val_eq; -- 1
SELECT * FROM old_t o JOIN new_t n ON o.id = n.id
WHERE o.note <=> n.note;Ściąga dotycząca różnic między dialektami
Rekruterzy doceniają kandydatów, którzy znają granice przenośności. Oto zestawienie porównań bezpiecznych dla NULL:
- ANSI / Postgres / SQL Server 2022+:
IS NOT DISTINCT FROM - MySQL / MariaDB:
<=> - SQLite:
ISiIS NOTdziałają jako porównanie bezpieczne dla NULL - Oracle: brak natywnego operatora; można go emulować za pomocą
DECODE(a, b, 1, 0) = 1lub sztuczek z COALESCE
Jeśli nie ma pewności, z jakim silnikiem ma się do czynienia, należy użyć przenośnej postaci ręcznej przedstawionej dalej.
-- SQLite NULL-safe equality
SELECT * FROM t WHERE a IS b; -- TRUE when both NULL
SELECT * FROM t WHERE a IS NOT b; -- complementRęczne, przenośne porównanie bezpieczne dla NULL
Gdy nie ma natywnego operatora, można zbudować bezpieczne dla NULL porównanie równościowe z podstawowych elementów. Przenośny wzorzec łączy zwykłe porównanie równości z jawnym warunkiem sprawdzającym, czy obie wartości są NULL.
Należy odczytywać go jako: „są równe LUB obie są nieobecne”. Działa on w każdej bazie danych, dlatego jest świetną odpowiedzią, gdy rekruter nie określi dialektu.
SELECT *
FROM old_t o JOIN new_t n ON o.id = n.id
WHERE (o.note = n.note)
OR (o.note IS NULL AND n.note IS NULL);
-- Alternative using COALESCE with a sentinel that
-- cannot occur in real data:
-- WHERE COALESCE(o.note, '##NULL##') = COALESCE(n.note, '##NULL##')Głębszy przykład: klucze JOIN bezpieczne dla NULL
Realistyczna pułapka: złączenie po kluczu dopuszczającym NULL. Jeśli region może mieć wartość NULL po obu stronach, zwykłe złączenie równościowe po cichu pomija takie pary, ponieważ NULL = NULL ma wartość UNKNOWN.
Jeśli reguła biznesowa brzmi: „wiersze bez regionu powinny nadal pasować do innych wierszy bez regionu”, warunek złączenia musi być bezpieczny dla NULL. Podczas rozmowy należy wyraźnie powiedzieć, jakie założenie jest przyjmowane, a następnie wybrać operator odpowiedni dla danego silnika.
-- Postgres / ANSI: match including both-NULL regions
SELECT a.id, b.id
FROM table_a a
JOIN table_b b
ON a.region IS NOT DISTINCT FROM b.region;
-- MySQL equivalent: ON a.region <=> b.regionNajważniejsze punkty na rozmowie
Aby poprawnie odpowiedzieć na każde pytanie dotyczące sprawdzania NULL:
- Zawsze należy używać
IS NULL/IS NOT NULL, nigdy= NULL. - Te predykaty zwracają wyłącznie TRUE albo FALSE, więc są bezpieczne w WHERE.
- Do dopasowywania, w którym „NULL równa się NULL”, należy użyć IS NOT DISTINCT FROM (ANSI) lub <=> (MySQL).
- Należy określić, jaki dialekt jest używany, a w razie niepewności zaproponować przenośną wersję z klauzulą OR.
Wymienienie zarówno operatora standardowego, jak i operatora dostawcy pokazuje szeroką znajomość tematu, co zauważają osoby prowadzące preselekcję.
Szybki test
Wybierz poprawne porównanie bezpieczne dla NULL.
Podsumowanie
Można już poprawnie sprawdzać NULL:
IS NULL/IS NOT NULLto jedyne poprawne i przenośne testy NULL; nigdy nie zwracają UNKNOWN.col = NULLzawsze zwraca zero wierszy; to klasyczna pułapka na rozmowach kwalifikacyjnych.- Porównanie bezpieczne dla NULL traktuje dwie wartości NULL jako równe: IS NOT DISTINCT FROM (ANSI/Postgres), <=> (MySQL), IS (SQLite).
- Gdy nie istnieje odpowiedni operator, należy użyć
(a = b) OR (a IS NULL AND b IS NULL).
Dalej: zastępowanie wartości NULL wartościami domyślnymi za pomocą COALESCE, NULLIF i funkcji dostawców, takich jak ISNULL.
Często zadawane pytania
Czy lekcja „IS NULL, IS NOT NULL i porównywanie bezpieczne dla NULL” jest bezpłatna?
Tak — pełny tekst „IS NULL, IS NOT NULL i porównywanie bezpieczne dla NULL” 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 Coding Interview Prep, przejdź na CoddyKit PRO. Kurs Coding Interview Prep zawiera 4 lekcji w sumie.
Co nauczysz się w „IS NULL, IS NOT NULL i porównywanie bezpieczne dla NULL”?
Poprawne testowanie wartości NULL oraz operatory bezpieczne dla NULL w poszczególnych dialektach Ćwiczysz Coding 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ąć Coding Interview Prep?
Nie wymagamy żadnego doświadczenia. Coding 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 2 z 4.
Ile czasu zajmuje lekcja „IS NULL, IS NOT NULL i porównywanie bezpieczne dla NULL”?
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 Coding Interview Prep?
Tak. Każda lekcja Coding 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