W tej części Darmowego Kursu SQL pokaże Ci czym jest wartość NULL. Dowiesz się na co zwrócić uwagę przy interpretacji wyników zapytań, które pobierają wiersze z taką wartością. Dodatkowo poznasz koncepcje Three-Valued Logic i potrzebne funkcje SQL!
Jesteś tutaj pierwszy raz? Nie widziałeś poprzednich lekcji? Zajrzyj tutaj: Kurs SQL #01: Wprowadzenie i środowisko
Czym jest NULL?
Do tej pory pokazałem Ci zapytania pobierające dane z bazy. No właśnie… dane, a co się dzieje w bazach danych jak nie ma w nich danych? Wiem, brzmi to dziwacznie, ale taka sytuacja jest wbrew pozorom częsta. Jak dobrze już wiesz, dane przechowywane są w tabelach. Tabele z kolei składają się z zdefiniowanych już na etapie ich tworzenia kolumn. Zastanawiałeś się już może co się dzieję kiedy w danym wierszu, dla którejś z kolumn porostu nie ma danych? Sytuacje taką właśnie reprezentuje wartość NULL!
Standardowo najlepiej rozpoznawać zagadnienie na przykładzie, więc rzuć okiem na poniższe zapytanie.
select
cust_id,cust_first_name, cust_last_name, cust_marital_status
from sh.customers
order by 1;
CUST_ID | CUST_FIRST_NAME | CUST_LAST_NAME | CUST_MARITAL_STATUS |
---|---|---|---|
1 | Abigail | Kessel | – |
2 | Anne | Koch | – |
3 | Buick | Emmerson | – |
4 | Frank | Hardy | – |
5 | Macklin | Gowen | – |
6 | Harriett | Charles | single |
7 | Linette | Ingram | single |
8 | Vida | Puleo | married |
9 | Rosamond | Krider | divorced |
10 | Gertrude | Atkins | widow |
Kolumna CUST_MARITAL_STATUS reprezentuje informacje na temat stanu cywilnego. Niektórzy z klientów nie podali swojego stanu cywilnego, dla nich właśnie wspomniana wcześniej kolumna ma wartość NULL. W przypadku Oracle Live SQL wartość ta pokazywana jest jako myślnik. Typowe narzędzia klienckie do bazy danych przeważnie pokazują wartość niewiadomą jako (null).
Gdybym miał powiedzieć w jednym zdaniu czym jest NULL, powiedziałbym że jest to wartość reprezentująca niewiadomą 😉
Należy pamiętać o tym, że pusty ciąg znakowy nie jest równoznaczny wartości NULL! Pusty ciąg znakowy jest konkretną wartością – nie jest niewiadomą.
Operatory dla NULL
NULL którego omawiam w tym artykule posiada także swoje operatory. Są nimi IS NULL i IS NOT NULL. Standardowo można je zastosować w klauzuli WHERE przy filtrowaniu wierszy.
select
cust_id,cust_first_name, cust_last_name, cust_marital_status
from sh.customers
where cust_marital_status is null
order by 1;
CUST_ID | CUST_FIRST_NAME | CUST_LAST_NAME | CUST_MARITAL_STATUS |
---|---|---|---|
1 | Abigail | Kessel | – |
2 | Anne | Koch | – |
3 | Buick | Emmerson | – |
4 | Frank | Hardy | – |
select
cust_id,cust_first_name, cust_last_name, cust_marital_status
from sh.customers
where cust_marital_status is not null
order by 1;
CUST_ID | CUST_FIRST_NAME | CUST_LAST_NAME | CUST_MARITAL_STATUS |
---|---|---|---|
6 | Harriett | Charles | single |
7 | Linette | Ingram | single |
8 | Vida | Puleo | married |
9 | Rosamond | Krider | divorced |
Jak widzisz zapytanie pierwsze zwróciło tylko rekordy z NULL. Drugie z kolei zwraca tylko te rekordy w których podana jest konkretna wartość w kolumnie CUST_MARITAL_STATUS.
Jeżeli preferujesz naukę prze oglądanie materiałów video zachęcam Cię do sprawdzenia mojego Kursu online SQL w Praktyce!
Kurs dostępny pod linkiem: Kurs SQL
Three-Valued Logic
Standardowa logika boolowska przewiduje dwie wartości – true i false. W przypadku sytuacji gdzie w logice występuje także wartość niewiadoma, czyli nasz NULL, mówimy już o logice trzech wartości(Three-Valued Logic). Zastanawiasz się dlaczego wchodzimy tutaj w tematy matematyczne i co to ma wspólnego z SQL?
Już odpowiadam, pamiętasz zapewne operatory które przerabialiśmy. Porównywanie wartości przy pomocy znaków <,> i = i logiki AND/OR Wyobraź sobie teraz, porównujesz w klauzuli WHERE wartość liczbową 100, a po drugiej stronie masz… NULL! Jaki będzie wynik takiego porównania?
Rzućmy okiem na przyjazne tabelki, a następnie wróćmy do naszego SQL 😉
Wartość | NOT |
---|---|
True | False |
False | True |
NULL | NULL |
AND | True | False | NULL |
True | True | False | NULL |
False | False | False | False |
NULL | NULL | False | NULL |
OR | True | False | NULL |
True | True | True | True |
False | True | False | NULL |
NULL | True | NULL | NULL |
Praktyczne zastosowanie Three-Valued Logic
Proste porównanie
select employee_id, first_name, last_name, salary, commission_pct
from hr.employees;
EMPLOYEE_ID | FIRST_NAME | LAST_NAME | SALARY | COMMISSION_PCT |
---|---|---|---|---|
100 | Steven | King | 24000 | – |
101 | Neena | Kochhar | 17000 | – |
102 | Lex | De Haan | 17000 | – |
103 | Alexander | Hunold | 9000 | – |
Zapytanie które widzisz wyżej pobiera dane z tabeli EMPLOYEES z schematu HR. Tabelka ta pokazuje pracowników firmy, ich zarobki, a także procentową premie którą otrzymują. Nie każdy pracownik dostaje premie, dlatego w kolumnie COMMISSION_PCT pojawia się wartość NULL. Przejrzyj wynik tego zapytania dokładnie, skup się na tym jak duże SALARY otrzymują pracownicy 😉
select employee_id, first_name, last_name, salary, commission_pct
from hr.employees
where salary + commission_pct*salary > 1200;
EMPLOYEE_ID | FIRST_NAME | LAST_NAME | SALARY | COMMISSION_PCT |
---|---|---|---|---|
145 | John | Russell | 14000 | .4 |
146 | Karen | Partners | 13500 | .3 |
147 | Alberto | Errazuriz | 12000 | .3 |
148 | Gerald | Cambrault | 11000 | .3 |
Zapytanie które przed chwilą zobaczyłeś filtruje pracowników. Chcemy wyświetlić tylko tych, których pensja z premią jest wyższa niż 1200. Gdy dokładnie przejrzysz wynik tego zapytania, zauważysz że lista wyświetlonych osób jest dosyć krótka. Co więcej powinieneś zauważyć ciekawą rzecz, zostali pominięci wszyscy Ci których SALARY jest zdecydowanie powyżej 1200, ale nie mają przydzielonej żadnej premii!
Sytuacja wyżej opisana jest typowym przykładem logiki trzech wartości. Pracownicy którzy mają zarobki powyżej 1200, ale nie mający przydzielonej premii, nie zostali wyświetleni w wynikach zapytania. W ich przypadku jednym z elementów porównania „salary + commission_pct*salary > 1200” była wartość NULL, która spowodowała że wynik porównania stał się też NULL. Klauzula WHERE zwraca tylko te wiersze dla których wynik operacji logicznej to true 😉
⭐Zostań Administratorem Baz Danych! ⭐
Przejdź kompleksowy kurs: Praktyczna Administracja Oracle Database!
Operator AND
Poniższe zapytanie wykorzystuje bardziej złożony warunek z operatorem AND. W przypadku wystąpienia wartości niewiadomej w którymś z elementów operacji logicznej, wynik również jest niewiadomą.
select employee_id, first_name, last_name, salary, commission_pct
from hr.employees
where salary > 1200 and commission_pct > 0.2;
EMPLOYEE_ID | FIRST_NAME | LAST_NAME | SALARY | COMMISSION_PCT |
---|---|---|---|---|
145 | John | Russell | 14000 | .4 |
146 | Karen | Partners | 13500 | .3 |
147 | Alberto | Errazuriz | 12000 | .3 |
148 | Gerald | Cambrault | 11000 | .3 |
Tak jak w poprzednim przykładzie, w wyniku zapytania nie pojawiają się pracownicy bez przydzielonej premii.
Operator OR
Tym razem zmodyfikowałem zapytanie i wstawiłem do niego operator OR.
select employee_id, first_name, last_name, salary, commission_pct
from hr.employees
where salary > 1200 or commission_pct > 0.2;
EMPLOYEE_ID | FIRST_NAME | LAST_NAME | SALARY | COMMISSION_PCT |
---|---|---|---|---|
100 | Steven | King | 24000 | – |
101 | Neena | Kochhar | 17000 | – |
102 | Lex | De Haan | 17000 | – |
103 | Alexander | Hunold | 9000 | – |
W wynikach będziesz widzieć tym razem także pracowników bez premii. Operator logiczny OR wymaga by tylko jedna z stron zwróciła true, zatem wartość niewiadoma po drugiej stronie nie ma znaczenia, jeżeli tylko pierwsza ze stron zwraca true.
Funkcje NVL() i NVL2()
Musimy zatem poradzić sobie z problemem który pojawił się w poprzednich przykładach. Baza danych Oracle ma do tego celu przygotowane dwie funkcje.
Funkcja NVL()
Pierwsza z wspomnianych funkcji to NVL(). Ma ona dwa parametry, pierwszy z nich przyjmuje wartość która jest sprawdzana pod kątem bycia NULL. Drugi z parametrów to wartość która ma być wstawiona, jeżeli się okaże że wynik sprawdzenia zwrócił NULL.
select employee_id, first_name, last_name, salary, NVL(commission_pct, 0)
from hr.employees;
EMPLOYEE_ID | FIRST_NAME | LAST_NAME | SALARY | NVL(COMMISSION_PCT,0) |
---|---|---|---|---|
100 | Steven | King | 24000 | 0 |
101 | Neena | Kochhar | 17000 | 0 |
102 | Lex | De Haan | 17000 | 0 |
103 | Alexander | Hunold | 9000 | 0 |
Jak widzisz wszędzie tam gdzie wartość była niewiadomą, mamy teraz konkretną wartość, w tym wypadku 0. W wierszach gdzie była podana wartość premii, dane pokazywane są bez zmian.
Funkcja NVL2()
Funkcja NVL2() różni się od poprzedniej dodatkowym, trzecim parametrem. Możemy użyć go w celu podmieniana dodatkowo wartości dla których nie wyszedł NULL podczas sprawdzenia. Najlepiej zobacz to na przykładzie 😉
select employee_id, first_name, last_name, salary, NVL2(commission_pct, 0,0.1)
from hr.employees;
EMPLOYEE_ID | FIRST_NAME | LAST_NAME | SALARY | NVL2(commission_pct, 0,0.1) |
143 | Randall | Matos | 2600 | .1 |
144 | Peter | Vargas | 2500 | .1 |
145 | John | Russell | 14000 | 0 |
146 | Karen | Partners | 13500 | 0 |
Funkcja NVL2() podmieniła nieznane wartości na 0, natomiast wartości inne znane na 0.1 😉
Zadanie domowe!
Naszym celem jest wyświetlenie listy pracowników, którzy zarabiają więcej niż 1200, niezależnie od tego czy dostają premie czy nie. Jak zatem należy poprawić poniższe zapytanie, aby pozyskać właściwy zestaw danych?
select employee_id, first_name, last_name, salary, commission_pct
from hr.employees
where salary + commission_pct*salary > 1200;
✅ Napisz w komentarzu poniżej jaka jest poprawna odpowiedź!✅
W kolejnej części Darmowego Kursu SQL pokażę Ci jak pobierać dane z wielu tabel jednocześnie.
Szósta część kursu już dostępna! Kurs SQL #06: Łączenie tabel