2013-03-14 16 views
5

Dzisiaj byłem zaskoczony tym case zachowań:przypadku, gdy wartość null FALSE

select case when null then true else false end; 
case 
------ 
f 

Spodziewam się, że powrót null ponieważ null lanego do logiczną yelds się null nie jest false:

select null::boolean is null; 
?column? 
---------- 
t 

Jakieś uwagi na temat racjonalnego uzasadnienia tego zachowania? Czego mi brakuje?

Odpowiedz

8

Myślisz o wyrażeniu CASE jakby brał null jako wejście do funkcji lub operatora, gdzie null wejście na ogół skutkuje zerowym wyjścia:

regress=> SELECT 't'::boolean = NULL::boolean; 
bool 
------ 

(1 row) 

wheras zachowuje się jak klauzula WHERE pod względem obsługi zerowej:

craig=> SELECT 't' WHERE NULL; 
?column? 
---------- 
(0 rows) 

W klauzulach WHERE - oraz w CASE, wynik NULL z wyrażenia testowego jest traktowany jako "nieprawdziwy, a zatem fałszywy". W pewnym sensie godne ubolewania jest to, że standard SQL nie spowodował wyrażenia NULL w wyrażeniu WHERE jako błędu zamiast traktowania go jako fałszywego, ale tak właśnie jest.

To kolejny bolesny objaw NULL „s rozdwojenie jaźni, gdzie spec SQL nie może zdecydować, czy NULL oznacza«Nieznany/wartość nieokreśloną»lub«braku wartości», podobnie jak okropny bałagan z NULL s i agregaty.

+0

Więc to tylko ze względu na specyfikację SQL? Deweloperzy PostgreSQL po prostu poszli za tym, zamiast robić "dobrą rzecz" _? Podejrzewałem, że tak było. –

+0

@ClodoaldoNeto Tak, i to jest prawie taka polityka, w której konflikt interesów dotyczy speca i zdrowego świata. W tym przypadku myślę, że jest to całkiem rozsądne; 'CASE' nie jest funkcją, jest specjalnym wyrażeniem z własnymi regułami. Funkcje i tak mogą mieć specjalne wartości zerowe; świadek 'dekodowania 'Oracle. PostgreSQL nie może tego naprawić bez przepisania specyfikacji SQL, aby całkowicie wyeliminować zamieszanie związane z wartościami zerowymi, co powoduje, że jest całkowicie niezgodny ze wszystkim innym. –

2

Jak PostgreSQL documentation stanów:

Jeśli nie Kiedy stan jest prawdziwe wtedy wartość wyrażenia case jest wynik w klauzuli indziej. Jeśli klauzula ELSE zostanie pominięta i żaden warunek nie zostanie spełniony, wynik jest zerowy.

Postgresql nie rzuca wyjście, a ponieważ masz kondycję else, dostajesz false. Następnego kwerenda zwraca wartość null (Ponieważ nie ma else warunek)

select case when null then true end; 
+0

_If gdy warunek nie jest true_ Gdy warunek jest 'null' nie można powiedzieć, że to nie jest prawdą. Nie wiesz. Może to być prawda lub fałsz. –

+3

Czy "null = true" jest prawdziwe? Nie, jest puste. Oznacza to, że pierwsza gałąź jest odrzucana, a druga odbywa się. Testy warunkowe w SQL nie są oparte na logice. Stąd cały ból mózgu spowodowany przez bezpańskie zero. –

1

CASE oświadczenie napisałeś posiada dwa oddziały:

Ten, when null then true, nigdy nie nastąpi (bo null nie jest równa true)

I oddział else, który nastąpi, gdy nie będzie pasować do zwykłych oddziałów when.

Przykład:

CASE WHEN val = 1 THEN 5 
    WHEN val = 2 THEN 10 
    ELSE 20 /*all other values, including null*/ 
END 
+0

Używając twojego przykładu, gdy 'val' ma wartość null, nie możesz powiedzieć, czy istnieje lub nie ma dopasowania, ponieważ' null = 1' ma wynik null nie false lub true. –

+0

@ ClodoaldoNeto: 'CASE' wpisuje pierwszą gałąź, w której warunek ma wartość" TRUE ". Jeśli żadna gałąź nie ma wartości "TRUE", wygrywa opcja "ELSE", której domyślnie brak 'NULL'. To cała historia. –

8

Zastosowanie coś

case when p.parent_id is null then false else true end as has_parent 
3

Można użyć 'select', aby sprawdzić kolumny danych dla wartości null:

select 
    ID, 
    case (select 1 where DATA is null) 
    when 1 then 'no data' 
    else data 
    end 
from ... 
8

W przypadku (także) potrzebują czegoś podobnego

if column is null then 'value' 

Użyj:

COALESCE(column_name, 'replacment for null value') as column_name 

W przypadku trzeba jeszcze oświadczenie case następnie użyć:

case COALESCE(column_name, 'asdf') 
when 'asdf' then true 
else false 
end as desired_column_name 
Powiązane problemy