Zusammenfassung

SQL verwendet eine dreiwertige Logik mit den Wahrheitswerten TRUE, FALSE und UNKNOWN, weil NULL-Werte (fehlende oder unbekannte Information) nicht wie normale Werte behandelt werden koennen. Vergleiche gegen NULL liefern stets UNKNOWN, und in arithmetischen Ausdruecken propagiert NULL (jede Operation mit NULL ergibt NULL). In der WHERE-Klausel werden nur Tupel uebernommen, deren Bedingung zu TRUE ausgewertet wird, waehrend FALSE und UNKNOWN gleichbehandelt verworfen werden.

Kernkonzepte

NULL-Semantik

NULL bedeutet unbekannter oder undefinierter Wert und ist kein regulaerer Wert eines Datentyps. NULL entsteht durch fehlende Eintraege, INSERT ohne Wert oder als Ergebnis von OUTER JOINs. NULL unterscheidet sich klar von 0 oder Leerstring: 0 ist bekannt und gleich 0, NULL ist unbekannt. Codds Regel 3 fordert einheitliche Behandlung von NULL unabhaengig vom Datentyp.

NULL heisst nicht null, sondern unbekannt.

Dreiwertige Logik

SQL kennt drei Wahrheitswerte: TRUE, FALSE und UNKNOWN. Der Wert UNKNOWN entsteht immer dann, wenn mindestens ein Operand eines Vergleichs NULL ist. Damit unterscheidet sich SQL von klassischer boolescher zweiwertiger Logik. AND, OR und NOT sind entsprechend erweiterte Wahrheitstafeln definiert.

TRUE, FALSE, UNKNOWN - drei Wahrheitswerte statt zwei.

NULL-Propagation in Arithmetik

Sobald in einer arithmetischen Operation ein Operand NULL ist, ist auch das Ergebnis NULL. Das gilt fuer Addition, Subtraktion, Multiplikation und sogar Division: 1+NULL, 5*NULL und 1/NULL ergeben alle NULL. Auch die String-Konkatenation mit || verhaelt sich so; nur concat() ignoriert NULL-Werte.

NULL infiziert die Rechnung - alles wird NULL.

WHERE-Filter und UNKNOWN

In die Ergebnismenge werden nur Tupel uebernommen, fuer die die WHERE-Bedingung zu TRUE auswertet. Tupel mit Ergebnis FALSE oder UNKNOWN werden ausgeschlossen. Deshalb liefert semester < 13 OR semester >= 13 fuer Tupel mit semester = NULL nicht die Tautologie TRUE, sondern UNKNOWN - solche Tupel verschwinden.

Nur TRUE ueberlebt WHERE - UNKNOWN wird wie FALSE verworfen.

IS NULL und IS NOT NULL

Da x = NULL immer UNKNOWN liefert, funktioniert der Gleichheitsvergleich nicht zum Test auf NULL. Stattdessen gibt es die Praedikate IS NULL und IS NOT NULL, die immer TRUE oder FALSE liefern (nie UNKNOWN). Zusaetzlich existieren DBMS-abhaengige Funktionen wie coalesce(), ifnull() und isnull().

NULL testet man mit IS NULL, nie mit = NULL.

Wahrheitstafeln AND und OR

Fuer AND gilt: UNKNOWN AND FALSE = FALSE, UNKNOWN AND TRUE = UNKNOWN, UNKNOWN AND UNKNOWN = UNKNOWN. Fuer OR gilt: UNKNOWN OR TRUE = TRUE, UNKNOWN OR FALSE = UNKNOWN, UNKNOWN OR UNKNOWN = UNKNOWN. NOT UNKNOWN ergibt UNKNOWN. Falls ein Operand allein das Ergebnis fixiert, ist der zweite egal.

AND mit FALSE bleibt FALSE, OR mit TRUE bleibt TRUE - sonst UNKNOWN.

NULL bei OUTER JOIN und Aggregation

LEFT/RIGHT/FULL OUTER JOINs erzeugen NULL fuer nicht gematchte Tupel. Das nutzt man fuer Anti-Joins: WHERE h.matrnr IS NULL findet Studenten ohne Vorlesung. Aggregatfunktionen wie count(spalte), sum(), avg() ignorieren NULL automatisch; nur count(*) zaehlt alle Zeilen.

OUTER JOIN erzeugt NULL - Aggregat ignoriert NULL - ALL braucht IS NOT NULL.

Primaerschluessel und NULL

Nach der Entity-Integritaet darf ein Primaerschluessel niemals NULL sein und muss eindeutig sein. Nullwerte sind nur in Attributen erlaubt, die nicht Teil eines Primaerschluessels sind. Bei Fremdschluesseln ist NULL erlaubt und bedeutet: Beziehung noch nicht bekannt.

Primaerschluessel: nie NULL. Fremdschluessel: darf NULL sein.

Wichtige Details

  • NULL ist kein Wert, sondern Platzhalter fuer fehlende oder unbekannte Information.
  • Vergleiche wie =, <, >, <> mit NULL ergeben immer UNKNOWN, niemals TRUE oder FALSE.
  • NULL = NULL liefert UNKNOWN, nicht TRUE - deshalb funktioniert Gleichheitstest auf NULL nicht.
  • Arithmetik mit NULL propagiert: jeder Ausdruck mit NULL wird NULL (auch 0 * NULL = NULL).
  • String-Konkatenation mit || ergibt NULL, wenn ein Operand NULL ist; concat() ignoriert NULL.
  • WHERE uebernimmt nur Tupel mit Ergebnis TRUE; FALSE und UNKNOWN werden verworfen.
  • Der BOOLEAN-Datentyp im SQL-Standard kennt selbst die Werte TRUE, FALSE und UNKNOWN.
  • Aggregatfunktionen (SUM, AVG, MIN, MAX, COUNT(spalte)) ignorieren NULL-Werte; nur COUNT(*) zaehlt alle Zeilen.
  • IS NULL und IS NOT NULL sind zweiwertig - sie liefern nie UNKNOWN.
  • OUTER JOINs erzeugen NULL fuer fehlende Match-Partner; ideal fuer Anti-Joins.
  • Primaerschluessel duerfen nicht NULL sein (Entity-Integritaet, Codds Regel).
  • NOT UNKNOWN ergibt UNKNOWN - Negation eines unbekannten Wahrheitswerts bleibt unbekannt.

Beispiele

Verschwundene Studenten trotz Tautologie

Studenten mit semester = NULL werden nicht gezaehlt, obwohl semester < 13 OR semester >= 13 scheinbar immer wahr ist. Grund: NULL < 13 = UNKNOWN, NULL >= 13 = UNKNOWN, UNKNOWN OR UNKNOWN = UNKNOWN - kein TRUE.

SELECT count(*)
FROM studenten
WHERE semester < 13 OR semester >= 13;

Ablauf fuer Tupel mit semester = NULL:
  (NULL < 13) = UNKNOWN
  (NULL >= 13) = UNKNOWN
  UNKNOWN OR UNKNOWN = UNKNOWN
  -> Tupel wird NICHT gezaehlt.

NULL-Propagation in Arithmetik

Jede arithmetische Verknuepfung mit NULL erzeugt NULL - unabhaengig vom Operator.

SELECT 1 + NULL;   -- Ergebnis: NULL
SELECT 5 * NULL;   -- Ergebnis: NULL
SELECT 1 / NULL;   -- Ergebnis: NULL (keine Division-durch-Null-Exception)
SELECT 0 * NULL;   -- Ergebnis: NULL (nicht 0!)

Anti-Join per LEFT OUTER JOIN und IS NULL

Studenten finden, die keine Vorlesung hoeren: LEFT OUTER JOIN erzeugt NULL fuer nicht gematchte Tupel, IS NULL filtert diese heraus.

SELECT s.matrnr
FROM studenten AS s
LEFT OUTER JOIN hoeren AS h
  ON s.matrnr = h.matrnr
WHERE h.matrnr IS NULL;

Ergebnis: alle Studenten ohne Eintrag in hoeren.

Wahrheitstafel-Auswertung Schritt fuer Schritt

Bedingung: (semester IS NOT NULL) AND (semester > 5). Fuer Tupel A mit semester=NULL und Tupel B mit semester=7.

Tupel A (semester = NULL):
  IS NOT NULL -> FALSE
  7 > 5 waere UNKNOWN, aber:
  FALSE AND UNKNOWN = FALSE (short-circuit)
  -> Tupel A raus.

Tupel B (semester = 7):
  IS NOT NULL -> TRUE
  7 > 5 -> TRUE
  TRUE AND TRUE = TRUE
  -> Tupel B im Ergebnis.

NULL bereinigen per UPDATE

Fehlende Semesterangaben auf 0 setzen. Ohne IS NULL wuerde WHERE semester = NULL nichts finden.

UPDATE studenten
SET semester = 0
WHERE semester IS NULL;

Grafik: Dreiwertige Logik

Die drei Wahrheitswerte TRUE FALSE UNKNOWN AND AND T U F T T U F U U U F F F F F U AND F = FALSE (FALSE dominiert) OR OR T U F T T T T U T U U F T U F U OR T = TRUE (TRUE dominiert) WHERE-Auswertung Tupel gegen WHERE Bedingung TRUE Ergebnis aufgenommen FALSE / UNKNOWN verworfen NULL-Propagation 5 * NULL NULL alles wird NULL

FAQ

Warum liefert NULL = NULL nicht TRUE?
Weil NULL unbekannt bedeutet - zwei unbekannte Werte koennten gleich oder ungleich sein. SQL entscheidet konservativ mit UNKNOWN und zwingt so zur expliziten Nutzung von IS NULL.
Warum reicht zweiwertige Logik nicht aus?
Weil NULL-Werte weder TRUE noch FALSE zugeordnet werden koennen ohne Bedeutungsverlust. Ein dritter Wahrheitswert UNKNOWN modelliert die Unsicherheit korrekt.
Was passiert bei WHERE mit UNKNOWN?
UNKNOWN wird in WHERE wie FALSE behandelt - das Tupel wird aus der Ergebnismenge ausgeschlossen. Nur bei TRUE bleibt das Tupel drin.
Wie zaehlt count() NULL-Werte?
count(spalte) ignoriert Zeilen, in denen die Spalte NULL ist. count(*) zaehlt dagegen alle Zeilen unabhaengig von NULL.
Was ergibt NOT UNKNOWN?
UNKNOWN. Die Negation eines unbekannten Wahrheitswerts ist selbst unbekannt.
Wie findet man alle Zeilen ohne Wert in einer Spalte?
Mit WHERE spalte IS NULL. WHERE spalte = NULL funktioniert nicht, da der Vergleich UNKNOWN liefert.
Warum liefert 0 * NULL nicht 0?
Weil NULL in Arithmetik propagiert - jede Operation mit NULL wird NULL, auch wenn ein Operand mathematisch alles absorbieren wuerde.
Wo entstehen NULL-Werte automatisch?
Bei OUTER JOINs fuer nicht gematchte Tupel, bei INSERT ohne Angabe eines Werts (falls nicht NOT NULL) und bei aggregierten Ausdruecken ueber leere Mengen.

Pruefungsfragen

0 von 0 Fragen beantwortet