thumb|Małą grecką literą omega (ω) oznacza się Null w teorii baz danych Null – specjalny znacznik w języku SQL, wskazujący, że dana nie istnieje w bazie danych. Wprowadzony przez twórcę relacyjnego modelu bazy danych, Edgara Franka Codda, znacznik Null istnieje, aby spełnić wymóg, że wszystkie prawdziwe systemy zarządzania relacyjną bazą danych udostępniają reprezentację „informacji brakującej i informacji niestosowalnej”. Codd zapoczątkował również przedstawianie znacznika Null w teorii baz danych za pomocą małej greckiej litery omega (ω). NULL to także zarezerwowane słowo w SQL, używane do identyfikacji specjalnego znacznika Null.

Znacznik Null był przedmiotem kontrowersji i powodem dyskusji z powodu powiązanej z nim logiki trójwartościowej, specjalnych wymagań wobec stosowania go w złączeniach i wymagania jego specjalnej obsługi w funkcjach agregujących i operatorach grupowania. Mimo wprowadzenia specjalnych funkcji i predykatów, aby właściwie obsługiwać znacznik Null, jego przeciwnicy uważają, że rozwiązywanie tych kwestii wprowadza niepotrzebne skomplikowanie i niekonsekwencję do relacyjnego modelu baz danych.

Historia Null został wprowadzony przez Edgara Franka Codda jako sposób na przedstawienie brakujących danych w modelu relacyjnym. W późniejszym czasie Codd, w dwuczęściowej serii opublikowanej w czasopiśmie ComputerWorld – Czy twoja baza jest naprawdę relacyjna? – Czy twój system zarządzania bazą danych działa zgodnie z zasadami?, wzmocnił swoje wymagania pisząc, że wszystkie RDBMS powinny wspierać Null, aby wskazać brakujące dane. Codd wprowadził również trójwartościową logikę składającą się z wartości logicznych Prawda, Fałsz i Nieznany, które są ściśle związane z pojęciem Null. Wartość logiczna Nieznany jest uzyskiwana gdy Null jest porównana z dowolną daną lub innym Null.

Codd wskazał w swojej książce The Relational Model for Database Management, Version 2 z 1990 roku, że pojedynczy Null nakazany przez standard SQL jest niewystarczający i powinien być zastąpiony przez dwa wskaźniki typu Null, aby móc wskazać powód dlaczego danych brakuje. Te dwa znaczniki są powszechnie znane jako „wartości-A” i „wartości-I”, przedstawiające odpowiednio „brakujące, lecz dające się stosować” i „brakujące, lecz niewłaściwe”. Zalecenia Codda wymagałoby rozszerzenia systemu logiki SQL, aby umieścić cztery zmienne logiczne. Z powodu dodatkowych komplikacji, pomysł wielu wartości typu Null nie uzyskał powszechnej akceptacji.

Logika trójwartościowa

Ponieważ Null nie jest członkiem jakiejkolwiek domeny danych, nie jest on rozważany jako „wartość”, lecz raczej jako znacznik (lub symbol zastępczy) wskazujący na brak wartości. Z uwagi na to, porównywanie z Null nigdy nie może zwrócić Prawdy lub Fałszu, lecz zawsze trzeci logiczny wynik, Nieznany. Logiczny wynik poniższego wyrażenia, które porównuje wartość 10 z Null to Nieznany.

SELECT 10 = NULL -- Wynik to Nieznany

Jednakże w pewnych operacjach z Null, można otrzymać wartości, jeśli Null nie ma wpływu na wyniki takiej operacji. Rozważając następujący przykład:

SELECT NULL OR TRUE -- Wynik to Prawda

W tym przypadku, fakt, że wartość z lewej strony operatora sumy logiczniej (OR) jest nieznana jest bez znaczenia, ponieważ wynikiem tej sumy może być Prawda, niezależnie od wartości z lewej strony.

SQL realizuje trzy wyniki logiczne, czyli implementacje SQL muszą zapewnić specjalną logikę trójwartościową. Zasady rządzące trójwartościową logiką SQL są przedstawione w tabelach poniżej (p i q reprezentują stany logiczne).

p q p LUB q p I q p = q Prawda Prawda Prawda Prawda Prawda Prawda Fałsz Prawda Fałsz Fałsz Prawda Nieznany Prawda Nieznany Nieznany Fałsz Prawda Prawda Fałsz Fałsz Fałsz Fałsz Fałsz Fałsz Prawda Fałsz Nieznany Nieznany Fałsz Nieznany Nieznany Prawda Prawda Nieznany Nieznany Nieznany Fałsz Nieznany Fałsz Nieznany Nieznany Nieznany Nieznany Nieznany Nieznany p NIE p Prawda Fałsz Fałsz Prawda Nieznany Nieznany Tablica prawdy trójwartościowej logiki SQL

Podstawowe operatory porównujące w SQL zawsze zwracają Nieznany kiedy porównywane jest cokolwiek z Null, wobec czego standard SQL dostarcza dwa specjalne i specyficzne dla Null predykaty porównujące. Predykaty IS NULL i IS NOT NULL sprawdzają czy dana jest, albo nie jest, Null.

Typowanie danych W SQL Null nie ma typu, oznacza to, że nie jest on oznaczony jako liczba, znak lub jakikolwiek inny określony typ danych. Z tego powodu, czasami jest wymagane (lub pożądane) jawne konwertowanie Null do określonego typu danych. Na przykład, jeśli RDBMS wspiera przeciążanie funkcji, SQL może nie być w stanie automatycznie dowiązać właściwych funkcji bez znajomości typów danych wszystkich parametrów, włączając w nie te, które zostały przekazane jako Null.

Język przetwarzania danych Trójwartościowa logika SQL występuje w języku przetwarzania danych (DML) w predykatach porównujących, w wyrażeniach i zapytaniach DML. Klauzula WHERE powoduje, że wyrażenie DML działa tylko na wierszach dla których predykat zwraca Prawda. Wiersze, dla których predykat zwraca Fałsz lub Nieznany nie biorą udziału w wyrażeniach DML INSERT, UPDATE lub DELETE, oraz są pomijane w zapytaniach SELECT. Interpretowanie Nieznany i Fałsz jako takich samych logicznych wyników to powszechny błąd występujący przy działaniach z Null. Następujący prosty przykład demonstruje taką omyłkę:

SELECT * FROM t WHERE i = NULL;

Powyższy przykład zapytania logicznie zawsze zwraca zero wierszy ponieważ porównanie kolumny i z Null zawsze zwraca Nieznany, nawet dla wierszy w których i jest Null. Wynik Nieznany powoduje, że zapytanie SELECT szybko pominie wszystkie wiersze. (Chociaż, w praktyce, niektóre narzędzia SQL zwrócą wiersze stosując porównanie z Null.)

Wyrażenie CASE Wyrażenie SQL CASE dla Null działa na takich samych zasadach jak klauzula DML WHERE. Ponieważ może ono być rozwijane jako szereg warunków porównujących, proste wyrażenie CASE może sprawdzić wystąpienia Null bezpośrednio. Test na Null w prostym wyrażeniu CASE zawsze zwraca Nieznany, jak poniżej:

SELECT CASE i WHEN NULL THEN 'jest Null' -- To nigdy nie będzie zwrócone WHEN 0 THEN 'jest zero' -- To będzie zwrócone kiedy i = 0 WHEN 1 THEN 'jest jeden' -- To będzie zwrócone kiedy i = 1 END FROM t;

Ponieważ wyrażenie i = NULL jest rozwijane do Nieznany jest bez znaczenia jaką wartość ma kolumna i (nawet jeśli zawiera Null), tekst 'jest Null' nigdy nie będzie zwrócony.

Przeszukujące wyrażenie CASE także zwraca pierwszą wartość dla której wynik predykatu porównującego rozwija się do Prawda, włączając porównania stosujące predykaty IS NULL i IS NOT NULL. Następujący przykład pokazuje jak stosować przeszukujące wyrażenie CASE aby właściwie sprawdzać Null:

SELECT CASE WHEN i IS NULL THEN 'wynik Null' -- To jest zwrócone kiedy i jest NULL WHEN i = 0 THEN 'zero' -- To jest zwrócone kiedy i = 0 WHEN i = 1 THEN 'jeden' -- To jest zwrócone kiedy i = 1 END FROM t;

W przeszukującym wyrażeniu CASE, tekst 'wynik Null' jest zwrócone dla wszystkich wierszy w których i jest Null.

Ograniczenia definiowane Główne miejsce gdzie logika trójwartościowa krzyżuje się z językiem definicji danych (DDL) to zdefiniowane ograniczenia. Definiowane ograniczenie umieszczone na kolumnie działa pod nieco zmienionymi regułami, niż klauzula DML WHERE. Podczas gdy klauzula DML WHERE musi być rozwinięta do Prawda dla wiersza, ograniczenie definiowane nie może się rozwinąć do Fałsz. To znaczy, że ograniczenie definiowane powiedzie się jeśli wynik to Prawda lub Nieznany. Następująca przykładowa tabela ze zdefiniowanym ograniczeniem zabrania wstawienia każdej liczby całkowitej, ale pozwala na wstawienie Null, gdyż wynik sprawdzenia zawsze jest rozwijany do Nieznany dla Null.

CREATE TABLE t ( i INTEGER, CONSTRAINT ck_i CHECK ( i < 0 AND i = 0 AND i > 0 ) );

Aby wymusić ograniczenie na kolumnie aby nie akceptowała Nulli, można zastosować ograniczenie NOT NULL, jak to pokazano na przykładzie poniżej. Ograniczenie NOT NULL jest semantycznie równoważne z ograniczeniem definiowanym z predykatem IS NOT NULL.

CREATE TABLE t ( i INTEGER NOT NULL );

Rozszerzenia proceduralne SQL/PSM (ang. SQL Persistent Stored Modules – trwale przechowywane moduły) definiuje proceduralne rozszerzenia dla SQL, takie jak wyrażenie IF. Jednakże, główni dostawcy SQL historycznie zawierają swoje własne zastrzeżone rozszerzenia proceduralne. Proceduralne rozszerzenia dla pętli i porównań działają według reguł podobnych do zasad z wyrażeń i zapytań DML. Następujący fragment kodu, w standardzie ISO SQL, demonstruje użycie trójwartościowej logiki Null z wyrażeniem IF.

IF i = NULL THEN SELECT 'wynik to Prawda' ELSEIF NOT(i = NULL) THEN SELECT 'wynik to Fałsz' ELSE SELECT 'wynik to Nieznany';

Wyrażenie IF wykonuje akcję tylko dla tych porównań, które rozwijają się do Prawda. W wyrażeniach, w których się rozwija do Fałsz lub Nieznany, wyrażenie IF przekazuje sterowanie do klauzuli ELSEIF, a na końcu do klauzuli ELSE. Wynikiem kodu powyżej będzie zawsze wiadomość 'wynik to Nieznany' ponieważ porównania z Null zawsze zwracają Nieznany.

Złączenia Złączenia zewnętrzne, tj. lewe złączenie zewnętrzne, prawe złączenie zewnętrzne i pełne złączenie zewnętrzne, automatycznie umieszczają Null jako zamiennik dla wartości brakujących w powiązanych tabelach. Na przykład w lewym złączeniu zewnętrznym, Null jest umieszczany w miejscu brakujących wierszy z tabeli, która pojawia się po prawej stronie operatora LEFT OUTER JOIN. Następujący przykład używa dwóch tabel aby zademonstrować generowanie Null w lewym zewnętrznym złączeniu.

Pierwsza tabela (Pracownik) zawiera identyfikatory i nazwy pracowników, natomiast druga tabela (NumerTelefonu) zawiera powiązane z identyfikatorami pracowników numery telefonów, jak następuje.

+ Pracownik ID Nazwisko Imię 1 Jankowski Jacek 2 Krawiec Ludwik 3 Tomaszewski Tomasz 4 Pawlikowska Patrycja+ NumerTelefonu ID Numer 1 555-2323 3 555-9876

Następujący przykład zapytania SQL wykonuje lewe zewnętrzne złączenie na obu tych tabelach.

SELECT p.ID, p.Nazwisko, p.Imię, nt.Numer FROM Pracownik p LEFT OUTER JOIN NumerTelefonu nt ON p.ID = nt.ID;

Zbiór danych uzyskanych dzięki temu zapytaniu ukazuje jak SQL stosuje Null jako zamiennik dla brakujących danych z prawostronnej tabeli (NumerTelefonu), jak następuje.

+ Wynik zapytania ID Nazwisko Imię Numer 1 Jankowski Jacek 555-2323 2 Krawiec Ludwik NULL 3 Tomaszewski Tomasz 555-9876 4 Pawlikowska Patrycja NULL

W SQL istnieją również złączenia wewnętrzne i krzyżujące, które nie generują zamienników Null dla brakujących danych w powiązanych tabelach.

Należy zwrócić szczególną uwagę, w przypadkach gdy kolumny używane jako kryteria w złączeniach mogą zawierać Null. Ponieważ Null nie równa się jakiemukolwiek innemu Null, Nulle z jednej tabeli nie połączą się z Nullami z powiązanej kolumny z innej tabeli przy stosowaniu standardowych operatorów równości. W takich przypadkach przydatna jest funkcja SQL COALESCE lub wyrażenie CASE do „symulowania” równości z Null w kryteriach złączenia, jak również można stosować predykaty IS NULL lub IS NOT NULL.

Następujący predykat sprawdza równość wartości A i B, i traktuje Nulle jakby były równe. Operator IFNULL jest wymagany ponieważ A = B zwraca Null jeśli przynajmniej jeden z argumentów A lub B jest Null a NULL OR FALSE samo z siebie zwraca Null.

IFNULL( A = B, FALSE ) OR ( A IS NULL AND B IS NULL )

Operacje matematyczne i konkatenacja tekstów Ponieważ Null nie jest wartością danych, lecz raczej znacznikiem dla wartości nieznanej, używanie operatorów matematycznych na Null skutkuje wartością nieznaną, która jest reprezentowana przez Null. W następującym przykładzie, mnożenie 10 przez Null daje w wyniku Null:

10 * NULL -- Wynik to NULL