Zerowy (SQL) - Null (SQL)
Null lub NULL to specjalny znacznik używany w Structured Query Language do wskazania, że wartość danych nie istnieje w bazie danych . Wprowadzony przez twórcę relacyjnego modelu bazy danych, EF Codd , SQL Null spełnia wymóg, aby wszystkie prawdziwe systemy zarządzania relacyjnymi bazami danych ( RDMS ) obsługiwały reprezentację „brakujących informacji i nieodpowiednich informacji”. Codd wprowadził również użycie małego greckiego symbolu omega (ω) do reprezentowania wartości Null w teorii baz danych . W SQL NULL
jest zastrzeżonym słowem używanym do identyfikacji tego znacznika.
Nie należy mylić wartości null z wartością 0. Wartość null wskazuje na brak wartości, co nie jest tym samym, co wartość zero. Zastanówmy się na przykład nad pytaniem „Ile książek posiada Adam?” Odpowiedź może brzmieć „zero” ( wiemy, że nie posiada żadnego ) lub „null” ( nie wiemy, ile posiada). W tabeli bazy danych kolumna zawierająca tę odpowiedź zaczynałaby się bez wartości (oznaczona przez Null) i nie byłaby aktualizowana wartością „zero”, dopóki nie upewnimy się, że Adam nie posiada żadnych książek.
Wartość null SQL jest stanem, a nie wartością. To użycie jest zupełnie inne niż w większości języków programowania, gdzie null wartość referencji oznacza, że nie wskazuje ona żadnego obiektu .
Historia
EF Codd wspomniał o zerach jako metodzie przedstawiania brakujących danych w modelu relacyjnym w pracy z 1975 r. w Biuletynie FDT ACM - SIGMOD . Artykuł Codda, który jest najczęściej cytowany w związku z semantyką Null (przyjętą w SQL) to jego artykuł z 1979 roku w ACM Transactions on Database Systems , w którym przedstawił również swój Relational Model/Tasmania , chociaż wiele innych propozycji z te ostatnie dokumenty pozostały niejasne. Sekcja 2.3 jego pracy z 1979 r. szczegółowo opisuje semantykę propagacji wartości zerowych w operacjach arytmetycznych, a także porównania wykorzystujące logikę trójwartościową (trójwartościową) podczas porównywania z wartościami zerowymi; szczegółowo opisuje również traktowanie wartości Nulls w innych operacjach na zestawach (ta ostatnia kwestia jest dziś nadal kontrowersyjna). W kręgach teorii baz danych pierwotna propozycja Codda (1975, 1979) jest obecnie określana jako „tabele Codda”. Codd później wzmocnił swoje wymaganie, aby wszystkie RDBMS wspierały wartość Null w celu wskazania brakujących danych w dwuczęściowym artykule opublikowanym w 1985 roku w magazynie ComputerWorld .
Standard SQL z 1986 roku w zasadzie przyjął propozycję Codda po prototypie implementacji w IBM System R . Chociaż Don Chamberlin uznał null (obok zduplikowanych wierszy) za jedną z najbardziej kontrowersyjnych cech SQL, bronił projektu Nulls in SQL, powołując się na pragmatyczne argumenty, że jest to najtańsza forma wsparcia systemowego dla brakujących informacji, oszczędzając programistę przed wiele zduplikowanych sprawdzeń na poziomie aplikacji (patrz problem z półpredykatem ) przy jednoczesnym zapewnieniu projektantowi bazy danych opcji nieużywania wartości Null, jeśli sobie tego życzą; na przykład w celu uniknięcia dobrze znanych anomalii (omówionych w sekcji semantyki tego artykułu). Chamberlin argumentował również, że poza zapewnieniem funkcjonalności brakujących wartości, praktyczne doświadczenie z wartościami Null doprowadziło również do innych funkcji języka, które opierają się na wartościach Null, takich jak pewne konstrukcje grupujące i sprzężenia zewnętrzne. Na koniec argumentował, że w praktyce wartości Null są również wykorzystywane jako szybki sposób na załatanie istniejącego schematu, gdy musi on ewoluować poza pierwotną intencję, kodując nie po to, by brakowało, ale raczej na nieodpowiednie informacje; na przykład baza danych, która szybko musi obsługiwać samochody elektryczne, mając jednocześnie kolumnę mil na galon.
Codd wskazał w swojej książce z 1990 r. The Relational Model for Database Management, Version 2, że pojedynczy znak Null wymagany przez standard SQL jest niewystarczający i powinien zostać zastąpiony dwoma oddzielnymi znacznikami typu Null, aby wskazać przyczynę braku danych. W książce Codda te dwa znaczniki typu Null są określane jako „Wartości A” i „Wartości I”, reprezentujące odpowiednio „brakujące, ale możliwe do zastosowania” i „brakujące, ale nie dające się zastosować”. Zalecenie Codda wymagałoby rozszerzenia systemu logicznego SQL tak, aby mógł pomieścić czterowartościowy system logiczny. Z powodu tej dodatkowej złożoności pomysł wielu wartości zerowych z różnymi definicjami nie zyskał powszechnej akceptacji w domenie praktyków baz danych. Pozostaje jednak aktywnym polem badań, z licznymi artykułami wciąż publikowanymi.
Wyzwania
Null był przedmiotem kontrowersji i był źródłem debaty ze względu na związaną z nim logikę trójwartościową (3VL), specjalne wymagania dotyczące jego użycia w złączeniach SQL oraz specjalną obsługę wymaganą przez funkcje agregujące i operatory grupowania SQL. Profesor informatyki Ron van der Meyden podsumował różne kwestie następująco: „Niespójności w standardzie SQL oznaczają, że nie jest możliwe przypisanie żadnej intuicyjnej semantyki logicznej traktowaniu wartości zerowych w SQL”. Chociaż pojawiły się różne propozycje rozwiązania tych problemów, złożoność alternatyw uniemożliwiła ich powszechne przyjęcie.
Propagacja zerowa
Działania arytmetyczne
Ponieważ Null nie jest wartością danych, ale znacznikiem nieobecnej wartości, użycie operatorów matematycznych na Null daje nieznany wynik, który jest reprezentowany przez Null. W poniższym przykładzie pomnożenie 10 przez wartość Null daje wartość Null:
10 * NULL -- Result is NULL
Może to prowadzić do nieoczekiwanych rezultatów. Na przykład, gdy zostanie podjęta próba podzielenia wartości Null przez zero, platformy mogą zwrócić wartość Null zamiast zgłaszać oczekiwany „wyjątek danych – dzielenie przez zero”. Chociaż to zachowanie nie jest zdefiniowane przez standard ISO SQL, wielu dostawców DBMS traktuje tę operację podobnie. Na przykład platformy Oracle, PostgreSQL, MySQL Server i Microsoft SQL Server zwracają wynik Null dla następujących elementów:
NULL / 0
Łączenie ciągów
String konkatenacji operacje, które są powszechne w SQL prowadzić również w Null, gdy jeden z argumentów jest NULL. Poniższy przykład ilustruje wynik Null zwrócony przy użyciu wartości Null z ||
operatorem łączenia ciągów SQL .
'Fish ' || NULL || 'Chips' -- Result is NULL
Nie dotyczy to wszystkich implementacji baz danych. Na przykład w Oracle RDBMS NULL i pusty ciąg są uważane za to samo, a zatem 'Ryba' || NULL || „Frytki” daje w wyniku „Fryby rybne”.
Porównania z NULL i logiką trójwartościową (3VL)
Ponieważ Null nie należy do żadnej domeny danych , nie jest uważany za „wartość”, ale raczej za znacznik (lub symbol zastępczy) wskazujący niezdefiniowaną wartość . Z tego powodu porównania z wartością Null nigdy nie dają wyniku Prawda lub Fałsz, ale zawsze trzeci logiczny wynik, Nieznany. Logiczny wynik poniższego wyrażenia, które porównuje wartość 10 do Null, jest nieznany:
SELECT 10 = NULL -- Results in Unknown
Jednak niektóre operacje na Null mogą zwracać wartości, jeśli brak wartości nie ma znaczenia dla wyniku operacji. Rozważmy następujący przykład:
SELECT NULL OR TRUE -- Results in True
W tym przypadku fakt, że wartość po lewej stronie OR jest niepoznawalna, jest nieistotny, ponieważ wynik operacji OR byłby True niezależnie od wartości po lewej stronie.
SQL implementuje trzy logiczne wyniki, więc implementacje SQL muszą zapewniać wyspecjalizowaną logikę trójwartościową (3VL) . Reguły rządzące trójwartościową logiką SQL są pokazane w poniższych tabelach ( p i q reprezentują stany logiczne) " Tabele prawdy używane przez SQL dla AND, OR i NOT odpowiadają wspólnemu fragmentowi trójwartościowej logiki Kleene'a i Łukasiewicza ( które różnią się definicją implikacji, jednak SQL nie definiuje takiej operacji).
P | Q | p LUB q | p AND q | p = q |
---|---|---|---|---|
Prawdziwe | Prawdziwe | Prawdziwe | Prawdziwe | Prawdziwe |
Prawdziwe | Fałszywe | Prawdziwe | Fałszywe | Fałszywe |
Prawdziwe | Nieznany | Prawdziwe | Nieznany | Nieznany |
Fałszywe | Prawdziwe | Prawdziwe | Fałszywe | Fałszywe |
Fałszywe | Fałszywe | Fałszywe | Fałszywe | Prawdziwe |
Fałszywe | Nieznany | Nieznany | Fałszywe | Nieznany |
Nieznany | Prawdziwe | Prawdziwe | Nieznany | Nieznany |
Nieznany | Fałszywe | Nieznany | Fałszywe | Nieznany |
Nieznany | Nieznany | Nieznany | Nieznany | Nieznany |
P | NIE p |
---|---|
Prawdziwe | Fałszywe |
Fałszywe | Prawdziwe |
Nieznany | Nieznany |
Efekt klauzuli Nieznane w WHERE
Trójwartościowa logika SQL występuje w języku manipulacji danymi (DML) w predykatach porównania instrukcji i zapytań DML. WHERE
Klauzula powoduje oświadczenie DML do działania na tylko te wiersze, dla których predykat wartość true. Wiersze dla którego predykat Zwraca ono nieprawdziwe lub nieznanym nie działały przez INSERT
, UPDATE
lub DELETE
instrukcji DML i są odrzucane przez SELECT
zapytaniami. Interpretowanie nieznanych i fałszywych jako tego samego wyniku logicznego jest częstym błędem napotykanym podczas pracy z wartościami Null. Poniższy prosty przykład demonstruje ten błąd:
SELECT *
FROM t
WHERE i = NULL;
Przykładowe zapytanie powyżej logicznie zawsze zwraca zero wierszy, ponieważ porównanie kolumny i z wartością Null zawsze zwraca wartość Unknown, nawet dla tych wierszy, w których i ma wartość Null. Nieznany wynik powoduje, że SELECT
instrukcja sumarycznie odrzuca każdy wiersz. (Jednak w praktyce niektóre narzędzia SQL będą pobierać wiersze przy użyciu porównania z wartością Null.)
Predykaty porównawcze specyficzne dla null i specyficzne dla 3VL
Podstawowe operatory porównania SQL zawsze zwracają Unknown podczas porównywania czegokolwiek z wartością Null, więc standard SQL przewiduje dwa specjalne predykaty porównania specyficzne dla wartości Null. Te IS NULL
i IS NOT NULL
orzeczniki (wykorzystujące postfix składni) sprawdzania, czy dane, czy nie jest zerowy.
Standard SQL zawiera opcjonalną funkcję F571 „Testy wartości prawdy”, która wprowadza trzy dodatkowe logiczne operatory jednoargumentowe (w rzeczywistości sześć, jeśli policzymy ich negację, która jest częścią ich składni), również przy użyciu notacji postfiksowej. Mają następujące tabele prawdy:
P | p TO PRAWDA | p NIE JEST PRAWDA | p JEST FAŁSZ | p NIE JEST FAŁSZYWE | p JEST NIEZNANE | p NIE JEST NIEZNANE |
---|---|---|---|---|---|---|
Prawdziwe | Prawdziwe | Fałszywe | Fałszywe | Prawdziwe | Fałszywe | Prawdziwe |
Fałszywe | Fałszywe | Prawdziwe | Prawdziwe | Fałszywe | Fałszywe | Prawdziwe |
Nieznany | Fałszywe | Prawdziwe | Fałszywe | Prawdziwe | Prawdziwe | Fałszywe |
Funkcja F571 jest ortogonalna do obecności typu danych binarnych w SQL (omówione w dalszej części tego artykułu) i pomimo podobieństw składniowych F571 nie wprowadza do języka literałów logicznych lub trójwartościowych . Funkcja F571 była faktycznie obecna w SQL92 , na długo przed wprowadzeniem typu danych binarnych do standardu w 1999 roku. Funkcja F571 jest jednak zaimplementowana przez kilka systemów; PostgreSQL jest jednym z tych, którzy go implementują.
Dodanie IS UNKNOWN do innych operatorów trójwartościowej logiki SQL sprawia, że trójwartościowa logika SQL staje się funkcjonalnie kompletna , co oznacza, że jej operatory logiczne mogą wyrażać (w połączeniu) dowolną możliwą trójwartościową funkcję logiczną.
W systemach, które nie obsługują funkcji F571, można emulować IS UNKNOWN p , przeglądając każdy argument, który może spowodować, że wyrażenie p jest nieznane i testując te argumenty za pomocą IS NULL lub innych funkcji specyficznych dla NULL, chociaż może to być bardziej nieporęczny.
Prawo wykluczonej czwartej (w klauzulach WHERE)
W trójwartościowej logice SQL prawo wykluczonego środka , p OR NOT p , nie jest już prawdziwe dla wszystkich p . Dokładniej, w trójwartościowej logice SQL p OR NOT p jest nieznane dokładnie wtedy, gdy p jest nieznane, a w przeciwnym razie prawdziwe. Ponieważ bezpośrednie porównania z wartością Null dają nieznaną wartość logiczną, następujące zapytanie
SELECT * FROM stuff WHERE ( x = 10 ) OR NOT ( x = 10 );
nie jest równoważne w SQL z
SELECT * FROM stuff;
jeśli kolumna x zawiera jakiekolwiek wartości null; w takim przypadku drugie zapytanie zwróciłoby kilka wierszy, których nie zwraca pierwsze, a mianowicie wszystkie te, w których x jest Null. W klasycznej logice dwuwartościowej prawo wyłączonego środka pozwalałoby na uproszczenie predykatu WHERE, a właściwie jego eliminację. Próba zastosowania prawa wykluczonego środka do 3VL SQL jest w rzeczywistości fałszywą dychotomią . Drugie zapytanie jest właściwie równoważne z:
SELECT * FROM stuff;
-- is (because of 3VL) equivalent to:
SELECT * FROM stuff WHERE ( x = 10 ) OR NOT ( x = 10 ) OR x IS NULL;
Zatem poprawne uproszczenie pierwszej instrukcji w SQL wymaga zwrócenia wszystkich wierszy, w których x nie jest puste.
SELECT * FROM stuff WHERE x IS NOT NULL;
W związku z powyższym zauważ, że dla klauzuli WHERE języka SQL można zapisać tautologię podobną do prawa wykluczonego środka. Zakładając, że operator IS UNKNOWN jest obecny, p OR (NOT p ) OR ( p IS UNKNOWN) jest prawdziwe dla każdego predykatu p . Wśród logików nazywa się to prawem wykluczenia czwartego .
Istnieje kilka wyrażeń SQL, w których mniej oczywiste jest, gdzie pojawia się fałszywy dylemat, na przykład:
SELECT 'ok' WHERE 1 NOT IN (SELECT CAST (NULL AS INTEGER))
UNION
SELECT 'ok' WHERE 1 IN (SELECT CAST (NULL AS INTEGER));
nie generuje wierszy, ponieważ IN
przekłada się na iterowaną wersję równości względem zestawu argumentów, a 1<>NULL jest nieznane, podobnie jak 1=NULL jest nieznane. (CAST w tym przykładzie jest potrzebny tylko w niektórych implementacjach SQL, takich jak PostgreSQL, które w przeciwnym razie odrzuciłyby go z błędem sprawdzania typu. W wielu systemach w podzapytaniu działa zwykły SELECT NULL.) Brakujący przypadek powyżej to oczywiście:
SELECT 'ok' WHERE (1 IN (SELECT CAST (NULL AS INTEGER))) IS UNKNOWN;
Wpływ wartości Null i Unknown w innych konstruktach
Łączy
Sprzężenia oceniają przy użyciu tych samych reguł porównania, co w przypadku klauzul WHERE. Dlatego należy zachować ostrożność podczas używania kolumn dopuszczających wartość null w kryteriach sprzężenia SQL. W szczególności tabela zawierająca wartości null nie jest równa naturalnemu sprzężeniu własnemu, co oznacza, że podczas gdy jest to prawdą dla każdej relacji R w algebrze relacyjnej , samosprzężenie SQL wykluczy wszystkie wiersze mające gdziekolwiek wartość null. Przykład takiego zachowania podano w sekcji poświęconej analizie semantyki braków danych wartości Nulls.
COALESCE
Funkcji lub CASE
wyrażeń SQL można użyć do „symulowania” równości wartości Null w kryteriach łączenia, IS NULL
a IS NOT NULL
predykaty i mogą być również używane w kryteriach łączenia. Poniższy predykat sprawdza równość wartości A i B i traktuje wartości Nulls jako równe.
(A = B) OR (A IS NULL AND B IS NULL)
Wyrażenia CASE
SQL udostępnia dwa rodzaje wyrażeń warunkowych . Jedna z nich nazywa się "prostym PRZYPADKIEM" i działa jak instrukcja switch . Druga nazywa się w standardzie "przeszukiwanym CASE" i działa jak if...elseif .
Proste CASE
wyrażenia używają niejawnych porównań równości, które działają zgodnie z tymi samymi regułami, co WHERE
reguły klauzul DML dla wartości Null. Tak więc proste CASE
wyrażenie nie może bezpośrednio sprawdzić istnienia wartości Null. Sprawdzenie wartości Null w prostym CASE
wyrażeniu zawsze daje w wyniku Unknown, jak poniżej:
SELECT CASE i WHEN NULL THEN 'Is Null' -- This will never be returned
WHEN 0 THEN 'Is Zero' -- This will be returned when i = 0
WHEN 1 THEN 'Is One' -- This will be returned when i = 1
END
FROM t;
Ponieważ wyrażenie ma i = NULL
wartość Unknown bez względu na to, co zawiera kolumna wartości i (nawet jeśli zawiera wartość Null), ciąg 'Is Null'
nigdy nie zostanie zwrócony.
Z drugiej strony „wyszukiwane” CASE
wyrażenie może używać predykatów takich jak IS NULL
iw IS NOT NULL
swoich warunkach. Poniższy przykład pokazuje, jak używać wyszukiwanego CASE
wyrażenia, aby poprawnie sprawdzić, czy nie ma wartości Null:
SELECT CASE WHEN i IS NULL THEN 'Null Result' -- This will be returned when i is NULL
WHEN i = 0 THEN 'Zero' -- This will be returned when i = 0
WHEN i = 1 THEN 'One' -- This will be returned when i = 1
END
FROM t;
W wyszukiwanym CASE
wyrażeniu ciąg 'Null Result'
jest zwracany dla wszystkich wierszy, w których i ma wartość Null.
Dialekt SQL Oracle zapewnia wbudowaną funkcję, DECODE
która może być używana zamiast prostych wyrażeń CASE i uważa, że dwie wartości null są równe.
SELECT DECODE(i, NULL, 'Null Result', 0, 'Zero', 1, 'One') FROM t;
Na koniec wszystkie te konstrukcje zwracają wartość NULL, jeśli nie znaleziono dopasowania; mają ELSE NULL
klauzulę default .
Oświadczenia IF w rozszerzeniach proceduralnych
SQL/PSM (SQL Persistent Stored Modules) definiuje rozszerzenia proceduralne dla SQL, takie jak IF
instrukcja. Jednak główni dostawcy SQL historycznie uwzględniali własne, zastrzeżone rozszerzenia proceduralne. Rozszerzenia proceduralne dotyczące pętli i porównań działają zgodnie z regułami porównywania wartości Null, podobnie jak w przypadku instrukcji i zapytań DML. Poniższy fragment kodu, w standardowym formacie ISO SQL, demonstruje użycie wartości Null 3VL w IF
instrukcji.
IF i = NULL THEN
SELECT 'Result is True'
ELSEIF NOT(i = NULL) THEN
SELECT 'Result is False'
ELSE
SELECT 'Result is Unknown';
Do IF
rachunku wykonuje czynności wyłącznie dla tych porównań, które oceniają true. W przypadku instrukcji, które mają wartość False lub Unknown, IF
instrukcja przekazuje kontrolę do ELSEIF
klauzuli, a na końcu do ELSE
klauzuli. Wynikiem powyższego kodu zawsze będzie komunikat, 'Result is Unknown'
ponieważ porównania z wartością Null zawsze dają wartość Unknown.
Analiza semantyki brakujących wartości SQL Null
Przełomowa praca T. Imielińskiego i W. Lipskiego Jr. (1984) dostarczyła ram do oceny zamierzonej semantyki różnych propozycji implementacji semantyki brakującej wartości, która jest określana jako Algebry Imielińskiego-Lipskiego . Ta sekcja z grubsza podąża za rozdziałem 19 podręcznika „Alice”. Podobna prezentacja pojawia się w recenzji Ron van der Meyden, §10.4.
W selekcjach i projekcjach: słaba reprezentacja
Konstrukcje reprezentujące brakujące informacje, takie jak tabele Codd, są w rzeczywistości przeznaczone do reprezentowania zestawu relacji, po jednej dla każdego możliwego wystąpienia ich parametrów; w przypadku tabel Codd oznacza to zastąpienie wartości Null pewną konkretną wartością. Na przykład,
Nazwa | Wiek |
---|---|
Jerzy | 43 |
Harriet |
NULL
|
Karol | 56 |
Nazwa | Wiek |
---|---|
Jerzy | 43 |
Harriet | 22 |
Karol | 56 |
Nazwa | Wiek |
---|---|
Jerzy | 43 |
Harriet | 37 |
Karol | 56 |
Konstrukt (taki jak tabela Codda) jest uważany za system silnej reprezentacji (brakujących informacji), jeśli jakakolwiek odpowiedź na zapytanie zadane na konstrukcie może być uszczegółowiona w celu uzyskania odpowiedzi na każde odpowiadające zapytanie dotyczące relacji, które reprezentuje, co są postrzegane jako modele konstrukcji. Dokładniej, jeśli q jest formułą zapytania w algebrze relacyjnej (o „czystych” relacjach) i jeśli q jest jej podniesieniem do konstrukcji mającej reprezentować brakujące informacje, silna reprezentacja ma tę właściwość, że dla dowolnego zapytania q i (tabela) konstrukt T , q podnosi wszystkie odpowiedzi do konstruktu, tj.:
(Powyższe musi obowiązywać w przypadku zapytań przyjmujących dowolną liczbę tabel jako argumenty, ale ograniczenie do jednej tabeli wystarcza w tej dyskusji.) Oczywiście tabele Codd nie mają tej silnej właściwości, jeśli selekcje i projekcje są uważane za część języka zapytań. Na przykład wszystkie odpowiedzi na:
SELECT * FROM Emp WHERE Age = 22;
powinna zawierać możliwość istnienia relacji takiej jak EmpH22. Jednak tabele Codd nie mogą reprezentować alternatywy „wynik z możliwym 0 lub 1 wierszem”. Urządzenie, głównie teoretyczne, zwane tabelą warunkową (lub tabelą c) może jednak reprezentować taką odpowiedź:
Nazwa | Wiek | stan: schorzenie |
---|---|---|
Harriet | ω 1 | ω 1 = 22 |
gdzie kolumna warunku jest interpretowana jako wiersz nie istnieje, jeśli warunek jest fałszywy. Okazuje się, że ponieważ formuły w kolumnie warunku c-tablicy mogą być dowolnymi formułami logiki zdań , algorytm rozwiązywania problemu, czy c-tablica reprezentuje jakąś konkretną relację, ma złożoność współ-NP-zupełną , a zatem jest mało praktyczna wartość.
Pożądane jest zatem słabsze pojęcie reprezentacji. Imieliński i Lipski wprowadzili pojęcie słabej reprezentacji , które zasadniczo pozwala (podniesionym) zapytaniom o konstrukt zwrócić reprezentację tylko dla pewnych informacji, tj. czy jest ona prawidłowa dla wszystkich instancji (modeli) konstruktu „ świata możliwego ”. Konkretnie, konstrukcja jest słabym systemem reprezentacji, jeśli
Prawa strona powyższego równania to pewna informacja, czyli informacja, którą z pewnością można wydobyć z bazy danych niezależnie od tego, jakie wartości zostaną użyte do zastąpienia wartości Null w bazie danych. W przykładzie, który rozważaliśmy powyżej, łatwo zauważyć, że przecięcie wszystkich możliwych modeli (tj. pewnych informacji) wyboru zapytania jest w rzeczywistości puste, ponieważ na przykład zapytanie (niepodniesione) nie zwraca żadnych wierszy dla relacji EmpH37. Mówiąc bardziej ogólnie, Imieliński i Lipski wykazali, że tabele Codd są słabym systemem reprezentacji, jeśli język zapytań ogranicza się do projekcji, selekcji (i zmiany nazw kolumn). Jednak, gdy tylko dodamy do języka zapytań złączenia lub unię, nawet ta słaba właściwość zostanie utracona, jak pokazano w następnej sekcji.
WHERE Age = 22
Jeśli brane są pod uwagę łączenia lub związki: nawet słaba reprezentacja
Rozważ następujące zapytanie dotyczące tej samej tabeli Codd Emp z poprzedniej sekcji:
SELECT Name FROM Emp WHERE Age = 22
UNION
SELECT Name FROM Emp WHERE Age <> 22;
Jakakolwiek konkretna wartość zostałaby wybrana dla NULL
wieku Harriet, powyższe zapytanie zwróci pełną kolumnę nazw dowolnego modelu Emp , ale gdy (podniesione) zapytanie zostanie uruchomione na samym Emp , Harriet zawsze będzie brakować, tj. mamy :
Wynik zapytania na Emp : |
|
Wynik zapytania na dowolnym modelu Emp : |
|
Tak więc, gdy do języka zapytań dodawane są unie, tabele Codd nie są nawet słabym systemem reprezentacji brakujących informacji, co oznacza, że zapytania nad nimi nie przekazują nawet wszystkich pewnych informacji. Należy tutaj zauważyć, że semantyka UNION on Nulls, o której mowa w dalszej części, nawet nie wchodziła w grę w tym zapytaniu. „Zapominajki” charakter dwóch podzapytań wystarczył, aby zagwarantować, że niektóre pewne informacje nie zostaną zgłoszone, gdy powyższe zapytanie zostanie uruchomione w tabeli Codd Emp.
W przypadku sprzężeń naturalnych przykład potrzebny do pokazania, że pewne informacje mogą nie zostać zgłoszone przez niektóre zapytania, jest nieco bardziej skomplikowany. Rozważ stół
F1 | F2 | F3 |
---|---|---|
11 | NULL |
13 |
21 | NULL |
23 |
31 | 32 | 33 |
i zapytanie
SELECT F1, F3 FROM
(SELECT F1, F2 FROM J) AS F12
NATURAL JOIN
(SELECT F2, F3 FROM J) AS F23;
Wynik zapytania na J: |
|
Wynik zapytania na dowolnym modelu J: |
|
Intuicja co do tego, co dzieje się powyżej, jest taka, że tabele Codd reprezentujące prognozy w podzapytaniach tracą świadomość faktu, że wartości Null w kolumnach F12.F2 i F23.F2 są w rzeczywistości kopiami oryginałów w tabeli J. Ta obserwacja sugeruje, że stosunkowo prostym ulepszeniem tabel Codd (które działa poprawnie w tym przykładzie) byłoby użycie stałych Skolem (czyli funkcji Skolem, które są również funkcjami stałymi ), powiedzmy ω 12 i ω 22 zamiast pojedynczego symbolu NULL. Takie podejście, zwane tabelami v lub tabelami naiwnymi, jest mniej kosztowne obliczeniowo niż omówione powyżej tabele c. Jednak nadal nie jest to kompletne rozwiązanie dla niekompletnych informacji w tym sensie, że v-tabele są tylko słabą reprezentacją dla zapytań nie używających żadnych negacji w selekcji (i nie używających również żadnej różnicy zbiorów). Pierwszym przykładem rozważanym w tej sekcji jest użycie klauzuli negatywnej selekcji , więc jest to również przykład, w którym zapytania v-tabeli nie zgłaszają pewnych informacji.
WHERE Age <> 22
Sprawdź ograniczenia i klucze obce
Podstawowym miejscem, w którym trójwartościowa logika SQL przecina się z językiem DDL ( SQL Data Definition Language ), jest forma ograniczeń sprawdzających . Ograniczenie sprawdzające umieszczone na kolumnie działa według nieco innego zestawu reguł niż te dla WHERE
klauzuli DML . Podczas gdy WHERE
klauzula DML musi mieć wartość True dla wiersza, ograniczenie sprawdzające nie może mieć wartości False. (Z perspektywy logicznej wyznaczonymi wartościami są Prawda i Nieznane). Oznacza to, że ograniczenie sprawdzające powiedzie się, jeśli wynikiem sprawdzenia będzie Prawda lub Nieznane. Poniższa przykładowa tabela z ograniczeniem sprawdzania zabroni wstawiania dowolnych wartości całkowitych do kolumny i , ale pozwoli na wstawienie wartości Null, ponieważ wynik sprawdzenia będzie zawsze oceniany jako Unknown for Nulls.
CREATE TABLE t (
i INTEGER,
CONSTRAINT ck_i CHECK ( i < 0 AND i = 0 AND i > 0 ) );
Ze względu na zmianę wyznaczonych wartości względem klauzuli WHERE , z punktu widzenia logiki, prawo wyłączonego środka jest tautologią ograniczeń CHECK , co oznacza, że zawsze się udaje. Co więcej, zakładając, że wartości Null mają być interpretowane jako istniejące, ale nieznane wartości, niektóre patologiczne KONTROLE, takie jak powyższa, umożliwiają wstawianie wartości Null, których nigdy nie można zastąpić żadną wartością inną niż null.
CHECK (p OR NOT p)
Aby ograniczyć kolumnę do odrzucania wartości Null, NOT NULL
można zastosować ograniczenie, jak pokazano w poniższym przykładzie. NOT NULL
Ograniczeniem jest semantycznie równoważne ograniczenie wyboru z IS NOT NULL
orzecznika.
CREATE TABLE t ( i INTEGER NOT NULL );
Domyślnie ograniczenia sprawdzania kluczy obcych odnoszą sukces, jeśli którekolwiek z pól w takich kluczach ma wartość Null. Na przykład stół
CREATE TABLE Books
( title VARCHAR(100),
author_last VARCHAR(20),
author_first VARCHAR(20),
FOREIGN KEY (author_last, author_first)
REFERENCES Authors(last_name, first_name));
pozwoliłoby na wstawianie wierszy, w których autor_last lub autor_pierwszy są NULL
niezależnie od tego, jak zdefiniowano autorów tabeli lub co ona zawiera. Dokładniej, null w którymkolwiek z tych pól pozwalałby na dowolną wartość w drugim, nawet jeśli nie ma go w tabeli Authors. Na przykład, jeśli autorzy zawierali tylko ('Doe', 'John')
, ('Smith', NULL)
spełniłoby to ograniczenie klucza obcego. SQL-92 dodał dwie dodatkowe opcje zawężania dopasowań w takich przypadkach. Jeśli MATCH PARTIAL
zostanie dodany po REFERENCES
deklaracji, to każdy inny niż null musi pasować do klucza obcego, np. ('Doe', NULL)
nadal będzie pasował, ale ('Smith', NULL)
nie będzie pasował . Wreszcie, jeśli MATCH FULL
zostanie dodany, to ('Smith', NULL)
również nie będzie pasował do ograniczenia, ale (NULL, NULL)
nadal będzie pasował.
Połączenia zewnętrzne
Zewnętrzne sprzężenia SQL , w tym lewe sprzężenia zewnętrzne, prawe sprzężenia zewnętrzne i pełne sprzężenia zewnętrzne, automatycznie generują wartości Null jako symbole zastępcze brakujących wartości w powiązanych tabelach. Na przykład dla lewych sprzężeń zewnętrznych wartości Null są tworzone w miejscu brakujących wierszy w tabeli znajdujących się po prawej stronie LEFT OUTER JOIN
operatora. Poniższy prosty przykład używa dwóch tabel do zademonstrowania produkcji zastępczej wartości Null w lewym sprzężeniu zewnętrznym.
Pierwsza tabela ( Employee ) zawiera numery i nazwiska pracowników, natomiast druga tabela ( PhoneNumber ) zawiera powiązane numery ID pracowników i numery telefonów , jak pokazano poniżej.
|
|
Poniższe przykładowe zapytanie SQL wykonuje lewe sprzężenie zewnętrzne w tych dwóch tabelach.
SELECT e.ID, e.LastName, e.FirstName, pn.Number
FROM Employee e
LEFT OUTER JOIN PhoneNumber pn
ON e.ID = pn.ID;
Zestaw wyników wygenerowany przez to zapytanie pokazuje, w jaki sposób SQL używa wartości Null jako symbolu zastępczego dla wartości brakujących w tabeli po prawej stronie ( PhoneNumber ), jak pokazano poniżej.
NS | Nazwisko | Imię | Numer |
---|---|---|---|
1 | Johnson | Joe | 555-2323 |
2 | Chwytak | Larry |
NULL
|
3 | Thompson | Tomasz | 555-9876 |
4 | Patterson | Patrycja |
NULL
|
Funkcje agregujące
SQL definiuje funkcje agregujące, aby uprościć obliczenia agregujące po stronie serwera na danych. Z wyjątkiem COUNT(*)
funkcji wszystkie funkcje agregujące wykonują krok eliminacji wartości NULL, dzięki czemu wartości null nie są uwzględniane w końcowym wyniku obliczeń.
Zauważ, że eliminacja Null nie jest równoznaczna z zastąpieniem Null zerem. Na przykład w poniższej tabeli AVG(i)
(średnia wartości i
) da inny wynik niż AVG(j)
:
i | J |
---|---|
150 | 150 |
200 | 200 |
250 | 250 |
NULL
|
0 |
Oto AVG(i)
200 (średnia 150, 200 i 250), a AVG(j)
150 (średnia 150, 200, 250 i 0). Dobrze znanym skutkiem ubocznym tego jest to, że w SQL AVG(z)
jest to odpowiednik not SUM(z)/COUNT(*)
ale SUM(z)/COUNT(z)
.
Dane wyjściowe funkcji agregującej również mogą mieć wartość Null. Oto przykład:
SELECT COUNT(*), MIN(e.Wage), MAX(e.Wage)
FROM Employee e
WHERE e.LastName LIKE '%Jones%';
To zapytanie zawsze wygeneruje dokładnie jeden wiersz, zliczając liczbę pracowników, których nazwisko zawiera „Jones” i podając minimalną i maksymalną płacę znalezioną dla tych pracowników. Co się jednak stanie, jeśli żaden z pracowników nie spełni podanych kryteriów? Obliczenie minimalnej lub maksymalnej wartości pustego zestawu jest niemożliwe, więc te wyniki muszą być NULL, co oznacza brak odpowiedzi. Nie jest to wartość nieznana, jest to wartość Null reprezentująca brak wartości. Wynik byłby następujący:
LICZYĆ(*) | MIN(e.Płaca) | MAX(e.Płaca) |
---|---|---|
0 |
NULL
|
NULL
|
Gdy dwie wartości null są równe: grupowanie, sortowanie i niektóre operacje na zbiorach
Ponieważ SQL:2003 definiuje wszystkie znaczniki Null jako nierówne sobie, wymagana była specjalna definicja w celu grupowania wartości Null podczas wykonywania pewnych operacji. SQL definiuje „dowolne dwie wartości, które są sobie równe, lub dowolne dwie wartości Null”, jako „nie różniące się”. Ta definicja nie odrębny pozwala SQL do grupowania i sortowania wartości null, gdy GROUP BY
klauzula (i inne słowa kluczowe, które wykonują grupy) są stosowane.
Inne operacje SQL, klauzule i słowa kluczowe używają "not differ" w traktowaniu wartości Null. Należą do nich:
-
PARTITION BY
klauzula funkcji rankingowych i okienkowych, takich jakROW_NUMBER
-
UNION
,INTERSECT
, iEXCEPT
operator, które traktują wartości NULL jako takie same dla celów porównywania/eliminowania wierszy -
DISTINCT
słowo kluczowe używane wSELECT
zapytaniach
Zasada, że wartości null nie są sobie równe (ale wynik jest nieznany) jest skutecznie naruszana w specyfikacji SQL dla UNION
operatora, która identyfikuje ze sobą wartości null. W konsekwencji niektóre operacje na zbiorach w SQL, takie jak suma lub różnica, mogą dawać wyniki nie reprezentujące pewnych informacji, w przeciwieństwie do operacji obejmujących jawne porównania z wartością NULL (np. te w WHERE
klauzuli omówionej powyżej). W propozycji Codda z 1979 r. (która została zasadniczo przyjęta przez SQL92) ta niespójność semantyczna jest racjonalizowana przez argument, że usuwanie duplikatów w operacjach na zbiorach odbywa się „na niższym poziomie szczegółowości niż testowanie równości w ocenie operacji pobierania”.
Standard SQL nie definiuje jawnie domyślnej kolejności sortowania dla wartości Null. Zamiast tego w systemach zgodnych wartości Null mogą być sortowane przed lub po wszystkich wartościach danych, odpowiednio za pomocą klauzul NULLS FIRST
lub listy. Jednak nie wszyscy dostawcy DBMS implementują tę funkcjonalność. Sprzedawcy, którzy nie implementują tej funkcjonalności, mogą określić różne traktowanie sortowania zerowego w DBMS.
NULLS LAST
ORDER BY
Wpływ na działanie indeksu
Niektóre produkty SQL nie indeksują kluczy zawierających wartości NULL. Na przykład wersje PostgreSQL przed 8.3 nie, a dokumentacja indeksu B-drzewa stwierdza, że:
B-drzewa mogą obsługiwać zapytania dotyczące równości i zakresu na danych, które można posortować według pewnej kolejności. W szczególności, planer zapytań PostgreSQL rozważy użycie indeksu B-drzewa za każdym razem, gdy indeksowana kolumna jest zaangażowana w porównanie przy użyciu jednego z tych operatorów: < ≤ = ≥ >
Konstrukcje równoważne kombinacjom tych operatorów, takie jak BETWEEN i IN, mogą być również zaimplementowane z przeszukiwaniem indeksu B-drzewa. (Pamiętaj jednak, że IS NULL nie jest równoważne z = i nie można go indeksować).
W przypadkach, gdy indeks wymusza unikalność, wartości NULL są wykluczane z indeksu, a unikatowość nie jest wymuszana między wartościami NULL. Ponownie, cytuję z dokumentacji PostgreSQL :
Gdy indeks jest zadeklarowany jako unikatowy, wiele wierszy tabeli o równych indeksowanych wartościach nie będzie dozwolonych. Nulls nie są uważane za równe. Unikalny indeks wielokolumnowy odrzuci tylko przypadki, w których wszystkie indeksowane kolumny są równe w dwóch wierszach.
Jest to zgodne ze zdefiniowanym w SQL:2003 zachowaniem skalarnych porównań zerowych.
Innym sposobem indeksowania null polega ich obsługi, jak nie odrębny zgodnie z SQL: 2003 zdefiniowanego zachowania. Na przykład dokumentacja Microsoft SQL Server stwierdza, co następuje:
Do celów indeksowania wartości NULL są porównywane jako równe. Dlatego nie można utworzyć indeksu unikatowego lub ograniczenia UNIQUE, jeśli klucze mają wartość NULL w więcej niż jednym wierszu. Wybierz kolumny, które są zdefiniowane jako NOT NULL, gdy wybrano kolumny dla indeksu unikatowego lub ograniczenia unikatowego.
Obie te strategie indeksowania są zgodne ze zdefiniowanym w SQL:2003 zachowaniem wartości Null. Ponieważ metodologie indeksowania nie są wyraźnie zdefiniowane przez standard SQL:2003, strategie indeksowania dla wartości Null są całkowicie pozostawione dostawcom do zaprojektowania i wdrożenia.
Funkcje obsługi zerowej
SQL definiuje dwie funkcje do jawnej obsługi wartości Null: NULLIF
i COALESCE
. Obie funkcje są skrótami dla wyszukiwanych CASE
wyrażeń .
NULLIF
NULLIF
Funkcja dwa parametry. Jeśli pierwszy parametr jest równy drugiemu parametrowi, NULLIF
zwraca wartość Null. W przeciwnym razie zwracana jest wartość pierwszego parametru.
NULLIF(value1, value2)
Tak więc NULLIF
jest skrótem następującego CASE
wyrażenia:
CASE WHEN value1 = value2 THEN NULL ELSE value1 END
ŁĄCZYĆ
COALESCE
Funkcja przyjmuje listę parametrów zawracania pierwszej wartości nie-zerową z listy:
COALESCE(value1, value2, value3, ...)
COALESCE
jest zdefiniowany jako skrót dla następującego CASE
wyrażenia SQL :
CASE WHEN value1 IS NOT NULL THEN value1
WHEN value2 IS NOT NULL THEN value2
WHEN value3 IS NOT NULL THEN value3
...
END
Niektóre DBMS SQL implementują funkcje specyficzne dla dostawcy, podobne do COALESCE
. Niektóre systemy (np. Transact-SQL ) implementują ISNULL
funkcję lub inne podobne funkcje, które są funkcjonalnie podobne do COALESCE
. (Zobacz Is
funkcje, aby uzyskać więcej informacji na temat IS
funkcji w Transact-SQL).
NVL
Funkcja Oracle NVL
przyjmuje dwa parametry. Zwraca pierwszy parametr inny niż NULL lub NULL, jeśli wszystkie parametry mają wartość NULL.
COALESCE
Ekspresja może być przekształcony w równoważnej NVL
ekspresji w sposób następujący:
COALESCE ( val1, ... , val{n} )
przemienia się w:
NVL( val1 , NVL( val2 , NVL( val3 , … , NVL ( val{n-1} , val{n} ) … )))
Przypadkiem użycia tej funkcji jest zastąpienie w wyrażeniu NULL wartością, np. NVL(SALARY, 0)
„jeśli SALARY
jest NULL, zastąp ją wartością 0”.
Jest jednak jeden godny uwagi wyjątek. W większości implementacji COALESCE
ocenia swoje parametry, dopóki nie osiągnie pierwszego innego niż NULL, podczas gdy NVL
ocenia wszystkie swoje parametry. Jest to ważne z kilku powodów. Parametr po pierwszym parametrze innym niż NULL może być funkcją, która może być kosztowna obliczeniowo, nieprawidłowa lub może powodować nieoczekiwane skutki uboczne.
Wpisywanie danych Null i Unknown
NULL
Dosłowny jest bez typu SQL, co oznacza, że nie jest on oznaczony jako całkowitą, charakter, lub jakiegokolwiek innego specyficzny typ danych . Z tego powodu czasami jest obowiązkowe (lub pożądane) jawne przekonwertowanie wartości Null na określony typ danych. Na przykład, jeśli przeciążone funkcje są obsługiwane przez RDBMS, SQL może nie być w stanie automatycznie przetłumaczyć na właściwą funkcję bez znajomości typów danych wszystkich parametrów, w tym tych, dla których przekazano wartość Null.
Konwersja z NULL
literału na Null określonego typu jest możliwa przy użyciu CAST
wprowadzonego w SQL-92 . Na przykład:
CAST (NULL AS INTEGER)
reprezentuje nieobecną wartość typu INTEGER.
Rzeczywiste wpisywanie Unknown (różne lub nie od samego NULL) różni się w zależności od implementacji SQL. Na przykład następujące
SELECT 'ok' WHERE (NULL <> 1) IS NULL;
parsuje i wykonuje się pomyślnie w niektórych środowiskach (np. SQLite lub PostgreSQL ), które ujednolicają wartość logiczną NULL z Unknown, ale nie są w stanie przeanalizować w innych (np. w SQL Server Compact ). MySQL zachowuje się pod tym względem podobnie do PostgreSQL (z drobnym wyjątkiem, że MySQL traktuje TRUE i FALSE jako nie różniące się od zwykłych liczb całkowitych 1 i 0). PostgreSQL dodatkowo implementuje IS UNKNOWN
predykat, którego można użyć do sprawdzenia, czy trzywartościowy wynik logiczny jest nieznany, chociaż jest to tylko cukier składniowy.
typ danych BOOLEAN
Standard ISO SQL:1999 wprowadził typ danych BOOLEAN do SQL, jednak nadal jest to tylko opcjonalna, niepodstawowa funkcja, o kodzie T031.
Gdy jest ograniczony przez NOT NULL
ograniczenie, SQL BOOLEAN działa jak typ Boolean z innych języków. Jednak bez ograniczeń typ danych BOOLEAN, pomimo swojej nazwy, może zawierać wartości prawdy PRAWDA, FAŁSZ i NIEZNANE, z których wszystkie są zdefiniowane jako literały logiczne zgodnie ze standardem. Standard zapewnia również, że NULL i UNKNOWN "mogą być używane zamiennie, aby oznaczać dokładnie to samo".
Typ boolowski był przedmiotem krytyki, szczególnie ze względu na nakazane zachowanie literału NIEZNANEGO, który nigdy nie jest sobie równy ze względu na identyfikację z NULL.
Jak omówiono powyżej, w implementacji SQL w PostgreSQL , wartość Null jest używana do reprezentowania wszystkich NIEZNANYCH wyników, w tym UNKNOWN BOOLEAN. PostgreSQL nie implementuje literału UNKNOWN (chociaż implementuje operator IS UNKNOWN, który jest funkcją ortogonalną). Większość innych głównych dostawców nie obsługuje typu Boolean (zgodnie z definicją w T031) od 2012 roku. Część proceduralna PL Oracle /SQL obsługuje jednak zmienne BOOLEAN; można im również przypisać NULL, a wartość jest uważana za taką samą jak UNKNOWN.
Spór
Częste błędy
Niezrozumienie sposobu działania Null jest przyczyną dużej liczby błędów w kodzie SQL, zarówno w standardowych instrukcjach SQL ISO, jak i w konkretnych dialektach SQL obsługiwanych przez rzeczywiste systemy zarządzania bazami danych. Te błędy są zwykle wynikiem pomylenia wartości Null z 0 (zero) lub pustym ciągiem (wartość ciągu o długości zero, reprezentowana w SQL jako ''
). 0
Jednak wartość null jest zdefiniowana przez standard SQL jako różna zarówno od pustego ciągu znaków, jak i wartości liczbowej . Podczas gdy Null wskazuje na brak jakiejkolwiek wartości, pusty ciąg i zero numeryczne reprezentują rzeczywiste wartości.
Klasycznym błędem jest próba użycia operatora równości =
w połączeniu ze słowem kluczowym w NULL
celu znalezienia wierszy z wartościami Null. Według standardu SQL jest to nieprawidłowa składnia i powinna prowadzić do komunikatu o błędzie lub wyjątku. Ale większość implementacji akceptuje składnię i ocenia takie wyrażenia do UNKNOWN
. Konsekwencją jest to, że nie zostaną znalezione żadne wiersze – niezależnie od tego, czy wiersze z wartościami Null istnieją, czy nie. Proponowanym sposobem pobierania wierszy z wartościami Null jest użycie predykatu IS NULL
zamiast = NULL
.
SELECT *
FROM sometable
WHERE num = NULL; -- Should be "WHERE num IS NULL"
W podobnym, ale bardziej subtelnym przykładzie WHERE
klauzula lub instrukcja warunkowa może porównywać wartość kolumny ze stałą. Często błędnie zakłada się, że brakująca wartość byłaby „mniejsza niż” lub „nie równa” stałej, jeśli to pole zawiera wartość Null, ale w rzeczywistości takie wyrażenia zwracają Unknown. Przykład znajduje się poniżej:
SELECT *
FROM sometable
WHERE num <> 1; -- Rows where num is NULL will not be returned,
-- contrary to many users' expectations.
Te nieporozumienia powstają, ponieważ prawo tożsamości jest ograniczone w logice SQL. Kiedy mamy do czynienia z porównaniami równości przy użyciu NULL
literału lub wartości UNKNOWN
prawdziwości, SQL zawsze zwróci UNKNOWN
wynik wyrażenia. Jest to częściowa relacja równoważności i sprawia, że SQL jest przykładem logiki nierefleksyjnej .
Podobnie wartości null są często mylone z pustymi ciągami. Rozważmy LENGTH
funkcję, która zwraca liczbę znaków w ciągu. Po przekazaniu wartości Null do tej funkcji funkcja zwraca wartość Null. Może to prowadzić do nieoczekiwanych wyników, jeśli użytkownicy nie są dobrze zorientowani w logice trójwartościowej. Przykład znajduje się poniżej:
SELECT *
FROM sometable
WHERE LENGTH(string) < 20; -- Rows where string is NULL will not be returned.
Komplikuje to fakt, że w niektórych programach interfejsu baz danych (lub nawet implementacjach baz danych, takich jak Oracle), NULL jest zgłaszany jako pusty ciąg, a puste ciągi mogą być nieprawidłowo przechowywane jako NULL.
Krytyka
Implementacja Null ISO SQL jest przedmiotem krytyki, debaty i wzywa do zmian. W The Relational Model for Database Management: Version 2 Codd zasugerował, że implementacja SQL Null była błędna i powinna zostać zastąpiona dwoma różnymi znacznikami typu Null. Zaproponowane przez niego znaczniki miały oznaczać „Brakujące, ale możliwe do zastosowania” i „Brakujące, ale niemożliwe do zastosowania” , znane odpowiednio jako wartości A i I-wartości . Rekomendacja Codda, gdyby została zaakceptowana, wymagałaby implementacji czterowartościowej logiki w SQL. Inni sugerowali dodanie dodatkowych znaczników typu Null do zaleceń Codda, aby wskazać jeszcze więcej powodów, dla których wartość danych może być „Brakująca”, zwiększając złożoność systemu logicznego SQL. W różnych momentach pojawiały się również propozycje implementacji wielu zdefiniowanych przez użytkownika znaczników Null w SQL. Ze względu na złożoność systemów obsługi wartości Null i systemów logicznych wymaganych do obsługi wielu znaczników wartości Null, żadna z tych propozycji nie zyskała powszechnej akceptacji.
Chris Date i Hugh Darwen , autorzy The Third Manifesto , zasugerowali, że implementacja SQL Null jest z natury wadliwa i powinna zostać całkowicie wyeliminowana, wskazując na niespójności i błędy w implementacji obsługi SQL Null (szczególnie w funkcjach agregujących) jako dowód na to, że cała koncepcja Null jest błędna i powinna zostać usunięta z modelu relacyjnego. Inni, jak autor Fabian Pascal , wyrażają przekonanie, że „to, w jaki sposób obliczenia funkcji powinny traktować brakujące wartości, nie jest regulowane przez model relacyjny”.
Założenie zamkniętego świata
Innym punktem konfliktu dotyczącym wartości Null jest to, że łamią one model założenia o zamkniętym świecie relacyjnych baz danych, wprowadzając do niego założenie otwartego świata . Założenie zamkniętego świata, w odniesieniu do baz danych, mówi, że „Wszystko podane przez bazę danych, jawnie lub niejawnie, jest prawdziwe; wszystko inne jest fałszywe”. Ten widok zakłada, że wiedza o świecie przechowywana w bazie danych jest kompletna. Nulls działają jednak przy założeniu otwartego świata, w którym niektóre elementy przechowywane w bazie danych są uważane za nieznane, co sprawia, że przechowywana w bazie wiedza o świecie jest niekompletna.
Zobacz też
- SQL
- NULL w: Wikibook SQL
- Samouczek D
- Logika trójczłonowa
- Język manipulacji danymi
- 12 zasad dorsza
- Sprawdź ograniczenie
- Model relacyjny/Tasmania
- System zarządzania relacyjną bazą danych
- Dołącz (SQL)
- Trzeci manifest
Bibliografia
Dalsza lektura
- Dorsz EF Zrozumienie relacji (część 7). Biuletyn FDT ACM-SIGMOD, 7 (3-4): 23-28, 1975.
- Dorsz, EF (1979). „Rozszerzenie relacyjnego modelu bazy danych, aby uchwycić więcej znaczenia”. Transakcje ACM w systemach baz danych . 4 (4): 397–434. CiteSeerX 10.1.1.508.5701 . doi : 10.1145/320107.320109 . Zwłaszcza §2.3.
- Data, CJ (2000). Model relacyjny bazy danych: retrospektywny przegląd i analiza: relacja historyczna i ocena wkładu EF Codd w dziedzinę technologii baz danych . Addisona Wesleya Longmana . Numer ISBN 978-0-201-61294-3.
- Klein, Hans-Joachim (1994). "Jak modyfikować zapytania SQL w celu zagwarantowania pewnych odpowiedzi" . Rekord ACM SIGMOD . 23 (3): 14–20. doi : 10.1145/187436.187445 .
- Claude Rubinson, Nulls, Three-Valued Logic, and Ambiguity in SQL: Critiquing Date's Critique , SIGMOD Record, grudzień 2007 (tom 36, nr 4)
- John Grant, Wartości Null w SQL . Płyta SIGMOD, wrzesień 2008 (t. 37, nr 3)
- Waraporn, Narongrit i Kriengkrai Porkaew. " Semantyka null dla podzapytań i atomowych predykatów ". IAENG International Journal of Computer Science 35.3 (2008): 305-313.
- Bernhard Thalheim, Klaus-Dieter Schewe (2011). "NULL 'Wartości' Algebr i Logiki" . Granice w sztucznej inteligencji i zastosowaniach . 225 (Modelowanie informacji i bazy wiedzy XXII). doi : 10.3233/978-1-60750-690-4-354 .CS1 maint: używa parametru autorów ( link )
- Enrico Franconi i Sergio Tessaris, On the Logic of SQL Nulls , Proceedings of the 6th Alberto Mendelzon International Workshop on Foundations of Data Management, Ouro Preto, Brazylia, 27–30 czerwca 2012. s. 114–128
Zewnętrzne linki
- Wyrocznia NULL
- Trzeci manifest
- Implikacje wartości NULL w sekwencjonowaniu danych
- Raport o błędzie Java dotyczący jdbc nierozróżniającego łańcucha pustego i pustego, który Sun zamknął jako „nie jest to błąd”