Logo Oracle Deutschland   Application Express Community
NULL oder NOT NULL: Das ist hier die Frage!
Erscheinungsmonat APEX-Version Datenbankversion
September 2016 alle alle

Das Verhalten von SQL NULL (nicht nur) in der Oracle-Datenbank führt immer wieder zu Erstaunen und zu Überraschungen ... und dabei ist das eigentlich alles ganz einfach. Der heutige Community-Tipp beschreibt daher kurz und knapp das Verhalten von SQL NULL und worauf man (nicht nur) als APEX-Entwickler achten sollte.

Zunächst ist NULL definiert als der "unbekannte" Wert - NULL bedeutet also soviel wie "weiss nicht". So weit - so gut. Das Besondere ist nun, dass Oracle bei Vergleichen mit "dreiwertiger" Logik arbeitet: das Ergebnis eines Vergleichs kann also nicht nur wahr (true) oder falsch (false) sein, sondern auch weiss nicht, also NULL (Tabelle 1).

AusdruckErgebnis
{1} = {0}false
{1} = {1}true
{1} = {NULL}NULL
{NULL} = {NULL}NULL

Tabelle 1: Verhalten von SQL NULL bei Vergleichsoperationen

Die ersten beiden Zeilen sind klar; interessant ist die dritte. Der Vergleich 1 = NULL meint übersetzt soviel wie "Ist 1 gleich dem unbekannten Wert?" Die Antwort kann nur sein: "Weiss nicht", also NULL. Dasselbe gilt für den Vergleich NULL = NULL; das meint soviel wie "Ist ein unbekannter Wert gleich einem anderen unbekannten Wert?" Antwort wiederum: "Weiss nicht", also NULL. Das ist übrigens bei Negationen nicht anders (Tabelle 2).

AusdruckErgebnis
{1} != {0}true
{1} != {1}false
{1} != {NULL}NULL
{NULL} != {NULL}NULL

Tabelle 2: Verhalten von SQL NULL bei NOT-Vergleichsoperationen.

Der Aussagewert der Unbekannten ändert sich nicht, auch wenn man die Frage negiert. So meint 1 != NULL soviel wie " Ist 1 ungleich der Unbekannten?". Die Antwort lautet wiederum "Weiss nicht", könnte ja auch gleich sein. Möchte man in Vergleichen mit NULL arbeiten, so braucht man einen eigenen, speziellen Vergleichsoperator für SQL NULL (Tabelle 3).

AusdruckErgebnis
{1} IS NULLfalse
{NULL} IS NULLtrue
{NULL} IS NOT NULLfalse
{1} IS NOT NULLtrue

Tabelle 3: Operatoren IS NULL und IS NOT NULL

Der erste Vergleich meint übersetzt soviel wie "Ist 1 ein unbekannter Wert?" - das kann man klar beantworten: "1 ist bekannt", also "nein". Der Vergleich liefert also false zurück. Die nächste Zeile fragt, ob "der unbekannte Wert unbekannt ist"; das ist wahr; als Ergebnis kommt also true heraus.

Für den Entwickler bedeutet das, dass man bei Vergleichen mit NULL immer die dreiwertige Logik beachten muss - bei einem Vergleich mit Gleich, Ungleich, Größer oder Kleiner kommt niemals true, aber auch niemals false heraus. In einem IF-THEN-ELSE-Block landet man immer im ELSE-Zweig.

Verknüpft man NULL-Werte mit bool'schen Operatoren wie AND oder OR, so verhält sich SQL NULL ebenfalls etwas anders als bekannte Werte. Tabelle 4 enthält Details.

AusdruckErgebnis
{true} and {NULL}NULL
{false} and {NULL}false
{true} or {NULL}true
{false} or {NULL}NULL

Tabelle 4: AND, OR und SQL NULL

  • Fangen wir mit der ersten AND-Verknüpfung an: Die linke Seite ist mit true bekannt, die rechte Seite ist unbekannt (NULL). Das Ergebnis hängt also von der rechten Seite ab: Wenn die rechte Seite true wäre, wäre das Ergebnis ebenfalls true, wenn sie false wäre, dann ergäbe sich als Ergebnis false. Beides ist also möglich; also ergibt sich NULL als Ergebnis.
  • Bei der zweiten AND-Verküpfung ist die linke Seite mit false bekannt, die rechte Seite ist unbekannt (NULL). Nun ist es egal, wie die rechte Seite aussieht; wenn bei einer AND-Verknüpfung eine Seite false ist, kommt immer false heraus. Die Datenbank kann also mit Sicherheit sagen, dass false herauskommt.
  • Die OR-Verknüpfungen lassen sich ähnlich erklären. OR reagiert mit true genauso wie AND mit false. Hat eine Seite den Wert true, kommt immer true heraus. Die Datenbank kann also mit Sicherheit sagen, dass true herauskommt.
  • Die letzte OR-Verknüpfung mit false erklärt sich wie die erste AND-Verküpfung. Das Ergebnis hängt von der rechten Seite ab; die Datenbank weiss es also nicht; das Ergebnis ist NULL.

Daneben gibt es in der Oracle-Datenbank (wie immer) noch einige Besonderheiten ...

  • Der Leerstring in einem VARCHAR2 ist in Oracle als SQL NULL definiert. In Oracle kann man den Leerstring also nicht mit WHERE NAME = '' abfragen - nur mit WHERE NAME IS NULL. Das gilt jedoch nicht bei einem CLOB - dort gibt es sehr wohl einen Unterschied zwischen SQL NULL und einem leeren CLOB mit der Länge "0".
  • Bei Aggregatsfunktionen wird SQL NULL normalerweise ignoriert - nach dem bis hierher gelesenen müsste das Ergebnis einer Aggregatsfunktion wie SUM oder AVG stets SQL NULL sein, sobald sich auch nur ein NULL-Wert in den aggregierten Zeilen befindet. Das ist nicht der Fall - Oracle ignoriert die NULLs hier einfach - was ist der Praxis ja auch nützlicher ist.
  • Wenn es um das Gruppieren geht, wird NULL wie ein eigener, bekannter Wert behandelt - es wird also eine Gruppe für alle SQL NULLs gebildet. Das ist zwar strenggenommen nicht ganz richtig; man müsste eigentlich für jedes SQL NULL eine eigene Gruppe bilden - sowas wäre in der Praxis jedoch völlig unbrauchbar - so wie die Datenbank das macht, dürfte also die einzig sinnvolle Variante sein.

Der Umgang mit SQL NULL ist also einfacher als man denkt - solange man die "dreiwertige" Logik im Auge behält, die true, false oder NULL zurückgeben kann.

Zurück zur Community-Seite