2013-03-14 22 views
5

Heute wertet ich dieses case Verhalten überrascht wurde:Fall, wenn null auf false

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

Ich würde erwarten, dass es null seit einem null zu boolean gecastet zurückzukehren yelds eine null keine false:

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

Irgendwelche Kommentare zum Grundprinzip dieses Verhaltens? Was vermisse ich?

Antwort

8

Sie denken an den CASE Ausdruck wie es die null als Eingabe für eine Funktion oder Operator nehmen wurde, wo null Eingabe im Allgemeinen in null Ausgabeergebnisse:

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

(1 row) 

in der Tat verhält es sich in der Tat wie eine WHERE Klausel in Bezug auf Null Handhabung:

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

In WHERE Klauseln - und in CASE, wird ein NULL Ergebnis von einem Testausdruck als "nicht wahr und daher falsch" behandelt. In mancher Hinsicht ist es bedauerlich, dass der SQL-Standard kein NULL Ergebnis in einem WHERE Ausdruck einen Fehler gemacht hat, anstatt es als falsch zu behandeln, aber so ist es.

Dies ist ein weiteres schmerzhaftes Symptom NULL ‚s gespaltene Persönlichkeit, wo die SQL-Spezifikation nicht, wenn NULL bedeutet‚unbekannt/nicht definierten Wert‘oder‚das Fehlen eines Wertes‘, ähnlich wie das schreckliche Chaos mit NULL entscheiden kann, s und Aggregate.

+0

Also ist es nur wegen der SQL-Spezifikation? PostgreSQL-Entwickler haben es einfach übernommen, anstatt das "Richtige" zu tun _? Ich vermutete, dass das der Fall war. –

+0

@ClodoaldoNETO Ja, und das ist so ziemlich die Politik, wo die Spec und die gesunde Welt konfligieren. In diesem Fall denke ich, dass es durchaus vernünftig ist; 'CASE' ist keine Funktion, es ist ein spezieller Ausdruck mit eigenen Regeln. Funktionen können sowieso eine spezielle Nullbehandlung haben; Beachte Oracles "Dekodieren". PostgreSQL kann das nicht beheben, ohne die SQL-Spezifikation neu zu schreiben, um die Verwirrung über Nullen vollständig zu beheben und dabei völlig inkompatibel mit allem anderen da draußen zu sein. –

2

Als PostgreSQL documentation heißt es:

Wenn keine WHEN Bedingung wahr ist, dann wird der Wert des Case-Ausdruck ist die Ergebnis in der ELSE-Klausel. Wenn die ELSE-Klausel weggelassen wird und keine Bedingung übereinstimmt, ist das Ergebnis null.

Postgresql werfen nicht den Ausgang, und da Sie einen else Zustand haben, sind Sie false bekommen. Die nächste Abfrage einen Nullwert zurückgibt (Da es keine else Zustand ist)

select case when null then true end; 
+0

_If keine WHEN Bedingung true_ ist, wenn die Bedingung das Ergebnis 'null' Sie kann nicht sagen, es ist nicht wahr. Du weißt es nicht. Es könnte irgendeins von wahr oder falsch sein. –

+3

Ist "null = wahr" wahr? Nein, es ist null. Dies bedeutet, dass der erste Zweig abgelehnt wird und der Else stattfindet. Bedingte Tests in SQL sind nicht boolesch. Daher alle Hirnschmerzen, die durch streunende Nullen verursacht werden. –

1

Die CASE Aussage, die Sie geschrieben hat zwei Zweige:

Die eine, when null then true, wird nie passieren (weil null nicht gleich true ist)

Und else Zweig, das passiert, wenn es keine Übereinstimmungen in regulären when Filialen gibt.

Beispiel:

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

Mit Ihrem Beispiel, wenn 'val' null ist, können Sie nicht sagen, ob es eine Übereinstimmung gibt oder gibt, da' null = 1' ergibt null nicht falsch oder wahr. –

+0

@ClodoaldoNeto: 'CASE' tritt in den ersten Zweig ein, in dem die Bedingung 'TRUE' ergibt. Wenn keine Verzweigung "TRUE" ist, gewinnt "ELSE", wobei die Standardeinstellung "NULL" ist, wenn sie fehlt. Das ist die ganze Geschichte. –

8

Verwendung so etwas wie

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

können Sie 'wählen' DATA-Spalte für null überprüfen:

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

Falls Sie (auch) brauchen so etwas wie

if column is null then 'value' 

Verwendung:

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

Falls Sie noch eine Case-Anweisung, dann müssen verwenden:

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