Praktycznie wszystkie współczesne silniki baz danych implementuje logikę trójwartościową (three-valued logic). Ma to daleko idące konsekwencje dla szeregu działań na zbiorach danych. Wyrażenie logiczne języka SQL może mieć jedną z trzech wartości:
-
TRUE (prawda)
-
FALSE (fałsz)
-
UNKNOWN (nieokreśloność)
Wartość nieokreślona jest najczęściej skutkiem operacji, w których biorą udział NULLe. NULL to specjalna reprezentacja stanu braku, nieistnienia wartości. NULL może dotyczyć wartości dowolnego typu danych - od tinyint po nvarchar(max). Każde z poniższych przykładowych wyrażeń ma nieokreśloną wartość logiczną:
- NULL * 2
- NULL = NULL
- NULL = 5
Logiczna nieokreśloność NULLa i wyrażeń z jego udziałem to w bazach danych istotna i dość problematyczna kwestia. Z wyżej zaznaczonych powodów zapytanie:
SELECT colA, colB, colC FROM table WHERE colD = NULL;
jest semantycznie kłopotliwe i na pewno nie zwróci wyniku zgodnego z zamierzeniem. Lata temu wprowadzono więc do języka SQL specjalny operator IS, dzięki któremu możliwe jest skuteczne uwzględnianie NULLi. Konstrukcja:
SELECT colA, colB, colC FROM table WHERE colD IS NULL;
zadziała zgodnie z oczekiwaniami.
Trzeba przyznać, że obsługa NULLi w SQL Server jest niespójna, tzn. raz traktowane są jako logiczna prawda, a raz jako logiczny fałsz (prawdopodobnie trudno jednak wymyślić lepsze rozwiązanie). Wywoływać to może całą masę nieporozumień, dlatego deweloperzy powinni być na kwestię NULLi szczególnie uwrażliwieni. Oto kilka przykładów z obsługi:
1. GROUP BY
NULL traktowany jest jak wartość logiczna określona, tzn. że wyrażenie NULL = NULL zwraca prawdę i NULLe grupowane są do jednej grupy.
2. ORDER BY
NULLe traktowane są jak wartość określona (prawda) - są posortowane przy sobie.
3. kolumna UNIQUE
NULL traktowany jest jak wartość określona, tzn. że do kolumny z więzem UNIQUE nie można wstawić dwóch NULLi.
4. JOIN .. ON, HAVING, WHERE
NULL traktowany jest jak wartość logiczna fałszu - NULLe są eliminowane z wynikowego zbioru rekordów.
5. CHECK CONSTRAINT
NULL traktowany jest jak prawda. NULL > 0 spełni warunek CHECK sprawdzający, czy wartość jest dodatnia.
6. konkatenacja ciągów znakowych
NULL traktowany jest jako fałsz i sprowadza do fałszu całe wyrażenie. W poniższym przykładzie:
DECLARE @string varchar(10), @string_null varchar(10);
SET @string = 'text';
SET @string_null = NULL;
SET @string = 'slowo'+@string_null;
PRINT @string;
zmienna
@string będzie NULLem.
Na koniec warto jeszcze wspomnieć o funkcji ISNULL(), której wykorzystanie może pomóc w uzyskaniu zgodnego z oczekiwaniami efektu działania niektórych zapytań. Przykładowo: chcemy, aby rekordy były zjoinowane także w przypadku NULLi w filtrze ON:
SELECT colA, colB
FROM tab1 t1
INNER JOIN tab2 t2
ON (ISNULL(t1.colX1,'') = ISNULL(t2.colX2,''));