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 können. Vergleiche gegen NULL liefern stets UNKNOWN, und in arithmetischen Ausdrücken propagiert NULL (jede Operation mit NULL ergibt NULL). In der WHERE-Klausel werden nur Tupel übernommen, deren Bedingung zu TRUE ausgewertet wird, während FALSE und UNKNOWN gleichbehandelt verworfen werden.

Kernkonzepte

NULL-Semantik

NULL bedeutet unbekannter oder undefinierter Wert und ist kein regulärer Wert eines Datentyps. NULL entsteht durch fehlende Einträge, 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 unabhängig vom Datentyp.

NULL heißt 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 für Addition, Subtraktion, Multiplikation und sogar Division: 1+NULL, 5*NULL und 1/NULL ergeben alle NULL. Auch die String-Konkatenation mit || verhält sich so; nur concat() ignoriert NULL-Werte.

NULL infiziert die Rechnung - alles wird NULL.

WHERE-Filter und UNKNOWN

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

Nur TRUE überlebt 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 Prädikate IS NULL und IS NOT NULL, die immer TRUE oder FALSE liefern (nie UNKNOWN). Zusätzlich existieren DBMS-abhängige Funktionen wie coalesce(), ifnull() und isnull().

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

Wahrheitstafeln AND und OR

Für AND gilt: UNKNOWN AND FALSE = FALSE, UNKNOWN AND TRUE = UNKNOWN, UNKNOWN AND UNKNOWN = UNKNOWN. Für 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 für nicht gematchte Tupel. Das nutzt man für Anti-Joins: WHERE h.matrnr IS NULL findet Studenten ohne Vorlesung. Aggregatfunktionen wie count(spalte), sum(), avg() ignorieren NULL automatisch; nur count(*) zählt alle Zeilen.

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

Primärschlüssel und NULL

Nach der Entity-Integrität darf ein Primärschlüssel niemals NULL sein und muss eindeutig sein. Nullwerte sind nur in Attributen erlaubt, die nicht Teil eines Primärschlüssels sind. Bei Fremdschlüsseln ist NULL erlaubt und bedeutet: Beziehung noch nicht bekannt.

Primärschlüssel: nie NULL. Fremdschlüssel: darf NULL sein.

Wichtige Details

  • NULL ist kein Wert, sondern Platzhalter für 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 übernimmt 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(*) zählt alle Zeilen.
  • IS NULL und IS NOT NULL sind zweiwertig - sie liefern nie UNKNOWN.
  • OUTER JOINs erzeugen NULL für fehlende Match-Partner; ideal für Anti-Joins.
  • Primärschlüssel dürfen nicht NULL sein (Entity-Integrität, Codds Regel).
  • NOT UNKNOWN ergibt UNKNOWN - Negation eines unbekannten Wahrheitswerts bleibt unbekannt.

Beispiele

Verschwundene Studenten trotz Tautologie

Studenten mit semester = NULL werden nicht gezählt, 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 Verknüpfung mit NULL erzeugt NULL - unabhängig 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 hören: LEFT OUTER JOIN erzeugt NULL für 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 für Schritt

Bedingung: (semester IS NOT NULL) AND (semester > 5). Für 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 würde 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 könnten 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 können 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 zählt count() NULL-Werte?
count(spalte) ignoriert Zeilen, in denen die Spalte NULL ist. count(*) zählt dagegen alle Zeilen unabhängig 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 würde.
Wo entstehen NULL-Werte automatisch?
Bei OUTER JOINs für nicht gematchte Tupel, bei INSERT ohne Angabe eines Werts (falls nicht NOT NULL) und bei aggregierten Ausdrücken über leere Mengen.

Prüfungsfragen

0 von 0 Fragen beantwortet