Wartość NULL oznacza , ze dane pole w bazie danych lub zmienna w kodzie PL/SQL nie zostały zainicjowane... O ile powszechnie przy porównaniach stosowane są operatory IS NULL lub IS NOT NULL, inne ciekawsze przypadki nie zawsze są prawidłowo obsługiwane.
Zwróćmy uwagę że wartości NULL nie są porównywalne między sobą ani tez z innymi niepustymi wartościami... Oracle wg mnie powinien potraktować użycie NULL w warunkach po klauzuli WHERE przy operatorach porównujących jako błąd , wszelkie warunki typu a = NULL, a < NULL.
Dla operatorów arytmetycznych jest przyjęta zasada, jeśli co najmniej jeden argument IS NULL, to wartość też jest NULL. Dlatego zapytanie
SELECT 1 + NULL FROM dual zwróci wynik NULL
a zapytanie
SELECT NULL/0 FROM dual zwróci też NULL bez generowania wyjątku.
Zatem też poniższe zapytanie nie zwróci wyjątku, jeżeli co najmniej jeden ze składników sumy w mianowniku będzie niezainicjowany, mimo, że pozostałe będą sumować się do 0
SELECT (a+b+c+d) / e FROM tabela
jeśli którekolwiek z pól bazie miało wartość NULL, wynik będzie także NULL.
W wyrażeniach tekstowych należy zwrócić uwagę, że pusty tekst traktowany jest jako niezainicjowana wartość, co więcej długość takiego pola wynosi NULL, a nie zero
SELECT NVL(LENGTH(''), -1) FROM DUAL --zwraca -1
Zatem wszystkie poniższe trzy zapytania nie zwrócą żadnego rekordu, w każdym mamy porównanie względem wartości NULL
SELECT * FROM HR.EMPLOYEES WHERE LAST_NAME = ''
SELECT * FROM HR.EMPLOYEES WHERE LENGTH(LAST_NAME) =0
SELECT * FROM HR.EMPLOYEES WHERE LENGTH(LAST_NAME) < 1
Poniższe zapytanie nie pokaże rekordów, dla których pole COMMISSION_PCT ma wartość NULL
SELECT * FROM HR.EMPLOYEES WHERE COMMISSION_PCT IN (0.1, 0.2, NULL)
Prawidłowe wygląda następująco
SELECT * FROM HR.EMPLOYEES WHERE COMMISSION_PCT IN (0.1, 0.2) OR COMMISSION_PCT IS NULL
Z operatorem NOT IN sprawa wygląda ciekawiej, jeśli jedna wartość na liście jest pusta, to zapytanie nic nie zwróci
SELECT * FROM HR.EMPLOYEES WHERE COMMISSION_PCT NOT IN (0.1, 0.2, NULL)
Prawidłowe wygląda następująco
SELECT * FROM HR.EMPLOYEES WHERE COMMISSION_PCT NOT IN (0.1, 0.2) AND COMMISSION_PCT IS NOT NULL
Zgodnie z powyższą zasadą to zapytanie też nie zwróci rekordów - NULL został przemycony w pustym tekście
SELECT * FROM HR.EMPLOYEES WHERE LAST_NAME NOT IN ('Lorentz', '')