Pracując z bazami danych, każdy z nas spotkał się kiedyś z wartością NULL, która reprezentuje tak zwaną wartość nieznaną. Posiada ona specjalne wymagania przy
Warto zapoznać się głębiej z tymi cechami bo czasami mogą nas zaskoczyć.
1. Warunek NULL na kolumnie a
2. Warunek NOT NULL na wszystkich wierszach:
Zmieniam warunek zapytania i chcę jednak dostać wszystkie wiersze, gdzie kolumna b nie przyjmuje wartości 1 i 3. Wynik jest taki sam.
A IN (B) jest traktowane jako A =ANY B, a A NOT IN B jako NOT(A IN B).
Jednak A=ANY B wraca false jeśli A=b dla wszystkich b, które są w zbiorze B, a ponieważ A=NULL zwraca wartość nieznaną a nie false, to NOT IN nie może zwrócić wartości true.
Aby zabezpieczyć się przed takim scenariuszem, a nie możemy zmienić konstrukcji zapytania, musimy dodać warunek IS NOT NULL w podzapytaniu. (Pamiętajmy o tym gdy w warunku IN podstawiamy subselect)
Warto wiedzieć o specyficznych zachowaniach wartości NULL gdy mamy podejrzenie, że zwracany wynik naszego zapytania SELECT może być nieprawidłowy.
Powodzenia :-)
- złączeniach
- funkcjach agregujących
- operatorach grupowania
Warto zapoznać się głębiej z tymi cechami bo czasami mogą nas zaskoczyć.
Operator porównywania dla wartości NULL
exmaples=# \pset null 'NULL' Null display is "NULL". exmaples=# select 1 = NULL AS "1 = NULL", true OR NULL as "true OR NULL", true AND NULL as "true AND NULL", false OR NULL as "false OR NULL", false AND NULL as "false AND NULL", NULL = NULL as "NULL = NULL", NULL IS NULL as "NULL IS NULL"; -[ RECORD 1 ]--+----- 1 = NULL | NULL true OR NULL | t true AND NULL | NULL false OR NULL | NULL false AND NULL | f NULL = NULL | NULL NULL IS NULL | t
- Wyrażenie A = B mówi, że A "equal to" B. Porównanie wartości A do NULL wraca NULL nawet w przypadku gdy porównujemy dwie wartości NULL (NULL jest wartością NIEZNANĄ!)
- Operator IS jako argument przyjmuje wartości logiczne. Wartość logiczna z NULL odpowiada wartości nieznanej. Dlatego zwraca zawsze wartość boolean: true lub false
Wyszukiwanie wartości NULL i NOT NULL
Dla celów testowych stworzyłam tabelę o nazwie test_null, która przyjmuje dla niektórych wierszy w kolumnie a i b, wartości NULL. Poniżej zobaczycie podstawowe zapytania wyszukiwania wartości NULL.exmaples=# select * from test_null; a | b | c ------+------+--- NULL | 1 | f 1 | 2 | f NULL | 3 | f 2 | 3 | f NULL | NULL | f 3 | 2 | t 39 | 3 | t 39 | NULL | t 37 | 2 | t (9 rows)
1. Warunek NULL na kolumnie a
exmaples=# select * from test_null where a is NULL; a | b | c ------+------+--- NULL | 1 | f NULL | 3 | f NULL | NULL | f (3 rows)
2. Warunek NOT NULL na wszystkich wierszach:
exmaples=# select t.* from test_null t where t.* is NOT NULL; a | b | c ----+---+--- 1 | 2 | f 2 | 3 | f 3 | 2 | t 39 | 3 | t 37 | 2 | t (5 rows)
Polecenie SELECT z warunkiem IN i NOT IN
Dla powyższej tabeli chcielibyśmy wyciągnąć wiersze gdzie b jest równe 2 lub jest wartością NULL. Kiedy jednak wykonujemy poniższe zapytanie za pomocą operatora IN, wynik może nas zaskoczyć.Zmieniam warunek zapytania i chcę jednak dostać wszystkie wiersze, gdzie kolumna b nie przyjmuje wartości 1 i 3. Wynik jest taki sam.
exmaples=# select * from test_null where b IN (2,NULL); a | b | c ----+---+--- 1 | 2 | f 3 | 2 | t 37 | 2 | t (3 rows) exmaples=# select * from test_null where b NOT IN (1,3); a | b | c ----+---+--- 1 | 2 | f 3 | 2 | t 37 | 2 | t (3 rows)Jeśli jednak w warunku NOT IN pojawi się NULL, nie otrzymujemy już żadnych wierszy:
exmaples=# select * from test_null where b NOT IN (2,NULL); a | b | c ---+---+--- (0 rows)
A IN (B) jest traktowane jako A =ANY B, a A NOT IN B jako NOT(A IN B).
Jednak A=ANY B wraca false jeśli A=b dla wszystkich b, które są w zbiorze B, a ponieważ A=NULL zwraca wartość nieznaną a nie false, to NOT IN nie może zwrócić wartości true.
Aby zabezpieczyć się przed takim scenariuszem, a nie możemy zmienić konstrukcji zapytania, musimy dodać warunek IS NOT NULL w podzapytaniu. (Pamiętajmy o tym gdy w warunku IN podstawiamy subselect)
Funkcje agregujące i grupowanie
Dla tej samem tabeli testowej wyciągniemy podstawowe informację o ilości wierszy i sumie wartości kolumny b:exmaples=# select count(*), count(b), sum(b) from test_null; count | count | sum -------+-------+----- 9 | 7 | 16 (1 row)Grupowanie
exmaples=# select sum(a), b from test_null group by b having sum(a) < 40; sum | b -----+------ 39 | NULL (1 row)Wartości NULL nie są brane pod uwagę dla działania funkcji agregujących. Warunek Having działa tak samo jak dla operatory porównywania.
Warto wiedzieć o specyficznych zachowaniach wartości NULL gdy mamy podejrzenie, że zwracany wynik naszego zapytania SELECT może być nieprawidłowy.
Powodzenia :-)
Brak komentarzy:
Prześlij komentarz