2013-03-14 10 views
5

Oggi sono rimasto sorpreso da questo case comportamento:caso in cui nulla è falsa

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

mi aspetterei per tornare null dal momento che un null pressofuso ad booleano yelds un null non un false:

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

Qualche commento sulla logica di questo comportamento? Cosa mi manca?

risposta

8

State pensando alla CASE un'espressione come è stato tenuto il null come input per una funzione o operatore, dove ingresso nullo comporta generalmente uscita nullo:

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

(1 row) 

in cui si comporta come una clausola WHERE in termini di gestione nulla:

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

Nelle clausole WHERE - e in CASE, un risultato di NULL da un'espressione di test viene considerato come "non vero e quindi falso". In un certo senso è deplorevole che lo standard SQL non abbia reso un errore WHERE un'espressione WHERE invece di considerarlo falso, ma è così che è.

Questo è un altro sintomo doloroso di sdoppiamento della personalità NULL s', dove la specifica SQL non può decidere se NULL significa '/ valore sconosciuto non definito' o 'l'assenza di un valore', proprio come il pasticcio orribile con NULL s e aggregati.

+0

Quindi è solo a causa delle specifiche SQL? Gli sviluppatori di Postgresql l'hanno appena seguito invece di fare la "cosa giusta" _? Sospettavo che fosse il caso. –

+0

@ClodoaldoNeto Sì, ed è praticamente la politica in cui le specifiche e il mondo sano sono in conflitto. In questo caso, penso che sia abbastanza ragionevole, però; 'CASE' non è una funzione, è un'espressione speciale con le proprie regole. Le funzioni possono comunque avere una speciale gestione nulla; testimonia il 'decodifica 'di Oracle. PostgreSQL non è in grado di risolvere questo problema senza riscrivere le specifiche SQL per risolvere completamente la confusione relativa ai null, rendendola totalmente incompatibile con tutto il resto. –

2

quanto PostgreSQL documentation paese:

Se no quando condizione vale allora il valore dell'espressione caso è il risultato nella clausola ELSE. Se la clausola ELSE viene omessa e nessuna condizione corrisponde, il risultato è nullo.

PostgreSQL non gettato l'uscita, e dal momento che si dispone di una condizione di else, che stai ricevendo false. La prossima query restituisce un valore nullo (Dal momento che non c'è else condizione)

select case when null then true end; 
+0

_Se non quando la condizione è true_ Quando la condizione restituisce 'null' non si può dire che non è vero. Non lo sai Potrebbe essere qualsiasi di vero o falso. –

+3

"null = true" è vero? No, è nulla. Ciò significa che il primo ramo viene rifiutato e il resto avviene. I test condizionali in SQL non sono booleani. Quindi tutto il mal di cervello causato da nullamenti vaganti. –

1

Il CASE dichiarazione che hai scritto ha due rami:

L'uno, when null then true, non accadrà mai (perché null non è uguale a true

E il ramo else, che si verificherà quando non ci sono corrispondenze nelle filiali regolari when.

Esempio:

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

Usando il tuo esempio quando 'val' è nullo non puoi dire se c'è o non c'è una corrispondenza dato che 'null = 1' risulta null non falso né vero. –

+0

@ClodoaldoNeto: 'CASE' immette il primo ramo in cui la condizione restituisce" VERO ". Se nessun ramo è "VERO", vince "ELSE", che in default è "NULL" se mancante. Questa è l'intera storia. –

8

Usa qualcosa come

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

È possibile utilizzare 'selezionare' per controllare colonna di dati per nulla:

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

Nel caso in cui (anche) bisogno di qualcosa come

if column is null then 'value' 

Usa:

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

Nel caso in cui avete ancora bisogno di una dichiarazione caso quindi utilizzare:

case COALESCE(column_name, 'asdf') 
when 'asdf' then true 
else false 
end as desired_column_name 
Problemi correlati