Erklärte SQL-NULL-Werte: IS NULL, COALESCE, NULLIF und die zu vermeidenden Fallen
NULL verursacht einige der leisesten Fehler in SQL, mit Abfragen, die fehlerfrei ausgeführt werden, aber Zeilen verlieren oder Durchschnittswerte verzerren. Erfahren Sie anhand getesteter Beispiele, wie sich NULL wirklich verhält und wie Sie sicher damit umgehen.
- NULL bedeutet einen fehlenden oder unbekannten Wert. Es ist nicht Null und es ist keine leere Zeichenfolge.
- Testen Sie es mit
IS NULL, da= NULLnie mit irgendetwas übereinstimmt. - Die meisten Berechnungen mit NULL ergeben NULL, und
WHEREbehält nur Zeilen bei, die definitiv wahr sind. - Aggregate überspringen NULL-Werte, wodurch sich ein Durchschnitt stillschweigend ändern kann.
Eine Abfrage wird fehlerfrei ausgeführt und gibt eine sinnvoll aussehende Zahl zurück, es fehlen jedoch Zeilen und der Durchschnitt ist falsch. SQL-NULL-Werte sind sehr oft die Ursache. NULL verhält sich nicht wie ein normaler Wert, und das fällt sowohl Anfängern als auch erfahrenen Entwicklern auf.
Diese Anleitung zeigt genau, wie sich NULL verhält. Wir haben jede Abfrage in SQLite 3.50 ausgeführt und die angezeigten Ergebnisse stammen aus diesem Lauf. Der größte Teil dieses Verhaltens ist auf Standard-SQL zurückzuführen, und wir stellen fest, wo sich Datenbanken unterscheiden, z. B. in der NULL-Sortierreihenfolge und in der Behandlung leerer Zeichenfolgen durch Oracle.
Was ist NULL?
NULL ist ein Marker, der bedeutet, dass ein Wert fehlt oder unbekannt ist. Es handelt sich nicht um einen Wert im üblichen Sinne, das sind also alles verschiedene Dinge:
| Wert | Bedeutung | Beispiel für eine Telefonsäule |
|---|---|---|
NULL |
Unbekannt oder nicht angegeben | Wir kennen die Zahl nicht |
'' |
Ein bekannter, leerer Textwert | Als leer eingereicht |
0 |
Die Zahl Null | Nicht relevant für Text, aber real für Beträge |
Der Unterschied ist insbesondere bei Beträgen von Bedeutung. Ein Bonus von 0 bedeutet, dass die Person nichts erhalten hat. Ein NULL-Bonus bedeutet, dass es noch niemand weiß.
Die Beispieltabelle
CREATE TABLE employees (
id INT, name TEXT, phone TEXT, bonus INT, manager_id INT
);
INSERT INTO employees VALUES
(1,'Meera','555-0101',500,NULL),
(2,'Arjun',NULL,300,1),
(3,'Sara','',NULL,1),
(4,'Ravi',NULL,NULL,2);
Beachten Sie, dass Sara eine leere Zeichenfolge für das Telefon hat, während Arjun und Ravi NULL haben. Die beiden werden sehr unterschiedlich behandelt.
Testen auf NULL
Hier ist der Fehler, den fast jeder zuerst macht:
SELECT name FROM employees WHERE phone = NULL;
-- (no rows)
SELECT name FROM employees WHERE phone IS NULL;
-- Arjun
-- Ravi
SELECT name FROM employees WHERE phone IS NOT NULL;
-- Meera
-- Sara
Die erste Abfrage ist gültiges SQL und gibt keinen Fehler aus. Es wird einfach nichts zurückgegeben, da ein Vergleich mit NULL niemals wahr ist. Sara erscheint unter IS NOT NULL, da eine leere Zeichenfolge ein echter Wert ist. In Oracle wird eine leere Zeichenfolge jedoch als NULL behandelt, was eine bemerkenswerte Ausnahme darstellt.
Dreiwertige Logik
In den meisten Programmiersprachen ist eine Bedingung wahr oder falsch. SQL fügt ein drittes Ergebnis hinzu: unbekannt. Wenn Sie einen Wert nicht kennen, können Sie nicht sagen, ob er gleich 5 ist. Und es ist nicht bekannt, dass zwei unbekannte Werte gleich sind, weshalb NULL = NULL nicht wahr ist. In unserem Test gaben alle diese Werte NULL zurück:
SELECT NULL = NULL, NULL <> 1, 1 + NULL, 'a' || NULL;
-- NULL | NULL | NULL | NULL
Das Kombinieren von Bedingungen folgt sorgfältigen Regeln. Hier sind die Ergebnisse unseres Laufs, wobei 1 wahr und 0 falsch ist:
| Ausdruck | Ergebnis | Warum |
|---|---|---|
WAHR UND NULL |
NULL | Hängt vom unbekannten Teil ab |
FALSCH UND NULL |
Falsch | Falsch, was auch immer das Unbekannte ist |
WAHR ODER NULL |
Stimmt | Wahr, was auch immer das Unbekannte ist |
FALSCH ODER NULL |
NULL | Hängt vom unbekannten Teil ab |
NICHT NULL |
NULL | Das Gegenteil von unbekannt ist unbekannt |
Zeilen, die von WHERE verschwinden
WHERE behält eine Zeile nur, wenn ihre Bedingung wahr ist. Zeilen, deren Ergebnis unbekannt ist, werden gelöscht, zusammen mit Zeilen, die falsch sind. Dies führt zu überraschenden Ergebnissen:
SELECT name FROM employees WHERE phone <> '555-0101';
-- Sara
Man könnte erwarten, dass Arjun und Ravi auftauchen, da ihre Telefonnummer sicherlich nicht diese Nummer ist. Aber ihre Telefonnummer ist unbekannt, also ist das Ergebnis unbekannt und sie verschwinden. Um sie einzubeziehen, sagen Sie es ausdrücklich: WHERE phone <> '555-0101' OR phone IS NULL. Negation hilft auch nicht:
SELECT name FROM employees WHERE NOT (bonus > 400);
-- Arjun
Sara und Ravi haben keinen Bonus, daher erscheinen sie weder in bonus > 400 noch im Gegenteil. Dies ist ein wichtiger Punkt, den Sie im Hinterkopf behalten sollten: Eine Bedingung und ihre Negierung decken nicht immer jede Zeile ab.
COALESCE: einen Rückfall bieten
COALESCE gibt den ersten Nicht-NULL-Wert in seiner Liste zurück und funktioniert in allen wichtigen Datenbanken:
SELECT COALESCE(NULL, NULL, 'third', 'fourth');
-- third
SELECT name, COALESCE(phone, 'no phone') FROM employees;
-- Meera | 555-0101
-- Arjun | no phone
-- Sara |
-- Ravi | no phone
Sara erscheint immer noch leer, da eine leere Zeichenfolge nicht NULL ist. Es gibt ähnliche Funktionen, etwa IFNULL in MySQL und SQLite, ISNULL in SQL Server und NVL in Oracle. COALESCE ist die tragbare Wahl. Auch hier gilt unser früherer Hinweis zu Berechnungen. bonus + 100 gibt NULL für jeden ohne Bonus, also schreiben Sie COALESCE(bonus, 0) + 100, wenn es für Ihr Unternehmen korrekt ist, einen fehlenden Bonus als Null zu behandeln.
NULLIF: Wandelt einen Wert in NULL um
NULLIF(a, b) gibt NULL zurück, wenn die beiden Werte gleich sind, andernfalls wird a zurückgegeben. Zwei Anwendungen sind besonders hilfreich. Es kann Platzhalterwerte bereinigen:
SELECT name, NULLIF(phone, '') FROM employees WHERE id = 3;
-- Sara | NULL
SELECT name FROM employees
WHERE COALESCE(NULLIF(phone, ''), '') = '';
-- Arjun
-- Sara
-- Ravi
Diese zweite Abfrage ist eine praktische Möglichkeit, Werte zu finden, die „fehlen oder leer“ sind. Es kann auch vor einer Division durch Null schützen, die in vielen Datenbanken einen Fehler auslöst:
SELECT total / NULLIF(quantity, 0) FROM sales;
Wenn quantity 0 ist, ergibt dies NULL und schlägt nicht fehl. In unserem Test hat SELECT 100 / NULLIF(0, 0) NULL zurückgegeben.
Aggregate überspringen NULL
Hier richtet NULL bei Berichten den größten Schaden an:
SELECT COUNT(*), COUNT(bonus), SUM(bonus), AVG(bonus),
AVG(COALESCE(bonus, 0))
FROM employees;
-- 4 | 2 | 800 | 400.0 | 200.0
| Ausdruck | Ergebnis | Was es bedeutet |
|---|---|---|
COUNT(*) |
4 | Alle Reihen |
COUNT(bonus) |
2 | Nur Zeilen mit Bonus |
SUM(bonus) |
800 | NULL-Werte werden ignoriert |
AVG(bonus) |
400 | 800 geteilt durch 2, nicht durch 4 |
AVG(COALESCE(bonus, 0)) |
200 | 800 geteilt durch 4 |
Wie hoch ist also der durchschnittliche Bonus, 400 oder 200? Es hängt davon ab, was NULL in Ihren Daten bedeutet. Wenn NULL bedeutet „es wurde kein Bonus ausgezahlt“, dann ist 200 richtig. Wenn es „noch nicht entschieden“ bedeutet, dann könnte 400 richtig sein. Die Datenbank kann Ihnen diese Entscheidung nicht abnehmen, daher muss die Frage an jemanden gestellt werden, der sich mit dem Geschäft auskennt.
Eine verwandte Falle: SUM ohne Werte ist NULL statt 0. Wenn wir nur Zeilen ohne Bonus summierten, erhielten wir NULL, während COUNT 0 zurückgab. Anwendungscode, der eine Zahl erwartet, kann dabei abstürzen, also schließen Sie ihn ein: COALESCE(SUM(bonus), 0).
Tipp: Wenn die Berichtssumme nicht stimmt, vergleichen Sie COUNT(*) mit COUNT(column). Jede Lücke zwischen ihnen verrät Ihnen sofort, wie viele NULL-Werte diese Spalte enthält.
GROUP BY, Sortieren und DISTINCT
Obwohl NULL-Werte bei Vergleichen „ungleich“ sind, werden sie von diesen Operationen als eine Gruppe behandelt:
SELECT bonus, COUNT(*) FROM employees GROUP BY bonus ORDER BY bonus;
-- NULL | 2
-- 300 | 1
-- 500 | 1
SELECT DISTINCT bonus FROM employees;
-- 500, 300, NULL
Weitere Informationen zum Gruppieren finden Sie unter SQL GROUP BY und HAVING. In der Sortierreihenfolge unterscheiden sich Datenbanken wirklich. SQLite und MySQL behandeln NULL als den kleinsten Wert, während PostgreSQL und Oracle ihn als den größten behandeln. Dasselbe ORDER BY bonus DESC kann also NULL-Werte in einem an letzter Stelle und in einem anderen an erster Stelle setzen. Mit PostgreSQL, Oracle und modernem SQLite können Sie dies direkt angeben, indem Sie NULLS FIRST oder NULLS LAST verwenden.
Tritt bei
Eine Join-Bedingung mit = stimmt nie mit NULL überein, daher fallen Zeilen mit einem NULL-Schlüssel aus einem inneren Join heraus:
SELECT e.name FROM employees e
JOIN employees m ON m.id = e.manager_id;
-- Arjun, Sara, Ravi (Meera is gone)
SELECT e.name, m.name FROM employees e
LEFT JOIN employees m ON m.id = e.manager_id;
-- Meera | NULL
-- Arjun | Meera
-- Sara | Meera
-- Ravi | Arjun
Meera hat keinen Manager, daher löscht ein Inner Join diese Zeile stillschweigend. A LEFT JOIN behält es und erstellt auch eigene NULL-Werte für die fehlende Seite. Weitere Informationen finden Sie unter Erklärte SQL-Joins.
Die NICHT IN-Falle
Ein einzelner NULL-Wert in einer NOT IN-Liste löscht jedes Ergebnis:
SELECT name FROM employees WHERE manager_id NOT IN (1);
-- Ravi
SELECT name FROM employees WHERE manager_id NOT IN (1, NULL);
-- (no rows)
Die zweite Form bedeutet manager_id <> 1 AND manager_id <> NULL, und dieser letzte Teil kann niemals wahr sein. Dies ist besonders gefährlich bei Unterabfragen, bei denen ein NULL-Wert unbemerkt eintreffen kann. Verwenden Sie stattdessen NOT EXISTS, wie in unserem Tutorial zu SQL-Unterabfragen erläutert. Meera fehlt auch im ersten Ergebnis, da manager_id dieser Zeile NULL ist.
Entwerfen mit NULL
- Verwenden Sie standardmäßig
NOT NULL. Erlauben Sie NULL nur, wenn ein Wert wirklich fehlen kann. - Fügen Sie sinnvolle Standardeinstellungen hinzu. Zum Beispiel
quantity INT NOT NULL DEFAULT 0. - Verwenden Sie keine magischen Werte. Ein Datum von 1900-01-01 oder ein Alter von -1 anstelle von „unbekannt“ wird Ihre Berechnungen verfälschen.
- Kennen Sie das EINZIGARTIGE Verhalten. Die meisten Datenbanken erlauben mehrere NULL-Werte in einer Spalte
UNIQUEund unser Test hat zwei ohne Fehler eingefügt. Eine Ausnahme bildet SQL Server, da er dies normalerweise zulässt. - Denken Sie daran, dass ein Primärschlüssel nicht NULL sein kann. Siehe Primärschlüssel vs. Fremdschlüssel.
- Testen mit NULL-Werten. Testdaten ohne NULL-Werte verbergen diese Fehler. Fügen Sie sie absichtlich ein, wie Sie es auch in anderen Randfällen tun würden.
Fazit
Behandeln Sie NULL als „unbekannt“, und die meisten Verhaltensweisen beginnen einen Sinn zu ergeben: unbekannt plus eins ist unbekannt, und unbekannt ist gleich unbekannt, und es ist nicht bekannt, dass es wahr ist. Prüfen Sie diese Woche einen Ihrer eigenen Berichte. Überprüfen Sie nullfähige Spalten mithilfe von COUNT(*) gegenüber COUNT(column), suchen Sie nach NOT IN und entscheiden Sie, was NULL in jedem Durchschnitt bedeuten soll.
Häufige Fragen
Was ist NULL in SQL?
NULL ist ein Marker für einen fehlenden oder unbekannten Wert. Es unterscheidet sich von Null und einer leeren Zeichenfolge und erfordert bei Vergleichen eine besondere Behandlung.
Warum funktioniert = NULL nicht?
Der Vergleich von irgendetwas mit NULL ergibt unbekannt statt wahr, sodass WHERE die Zeile verwirft. Verwenden Sie IS NULL oder IS NOT NULL, um dies zu testen.
Was ist der Unterschied zwischen COALESCE und ISNULL?
COALESCE ist Standard-SQL und akzeptiert viele Argumente. ISNULL ist spezifisch für SQL Server und benötigt zwei. Für portablen Code bevorzugen Sie COALESCE.
Enthält COUNT NULL-Werte?
COUNT(*) zählt alle Zeilen, auch solche mit NULL-Werten. COUNT(column) zählt nur Zeilen, in denen diese Spalte nicht NULL ist, was zu einer kleineren Zahl führen kann.
Ist NULL dasselbe wie eine leere Zeichenfolge?
Nein, in den meisten Datenbanken. Eine leere Zeichenfolge ist ein bekannter Wert ohne Zeichen und NULL bedeutet unbekannt. Oracle ist eine bemerkenswerte Ausnahme, da es leere Zeichenfolgen als NULL behandelt.
Lerne weiter
Benötigen Sie Hilfe beim Testen, WordPress oder SEO?
Wir helfen Teams, bessere Software zu liefern und ihre Websites zu erweitern. Sagen Sie uns, woran Sie gerade arbeiten, und wir schlagen Ihnen einen klaren nächsten Schritt vor.
Weitere Anleitungen finden Sie unter Tests, KI und moderne Entwicklung
Hat Ihnen dieser Artikel gefallen? Wählen Sie ein Thema und springen Sie direkt in unsere neuesten Tutorials.
KI-Halluzinationen erklärt: Warum Sprachmodelle Dinge erfinden und wie man sie reduziert
KI-Halluzinationen erklärt: Was sie sind, warum Sprachmodelle sie produzieren, gängige Typen, wie man sie mit Erdung und Eingabeaufforderungen reduz…
Artikel lesen →DevOpsErklärte Umgebungsvariablen: .env-Dateien, Geheimnisse und Konfiguration richtig gemacht
Umgebungsvariablen anhand von Python-Beispielen erklärt, die wir ausgeführt haben: Sie lesen und festlegen, warum jeder Wert ein String ist, .env-Da…
Artikel lesen →SoftwareentwicklungAPI-Ratenbegrenzung erklärt: Algorithmen, Header und Behandlung von 429-Fehlern
API-Ratenbegrenzung anhand einer von uns durchgeführten Simulation erklärt: Token-Bucket, festes Fenster, gleitendes Fenster, 429 Antworten, Ratenbe…
Artikel lesen →TestautomatisierungSpott in Python: unittest.mock, Patch und die Fehler, die Tests zum Lügen machen
Mocking in Python mit unittest.mock, getestet: Mock und return_value, side_effect, Patchen, wo ein Name verwendet wird, Spezifikation und Autospec, …
Artikel lesen →SoftwaretestsCode-Abdeckung erklärt: Leitungs- und Zweigstellenabdeckung und was 100 % wirklich bedeutet
Erklärung der Codeabdeckung anhand eines echten Coverage.py-Laufs: Zeilen-, Zweig- und Bedingungsabdeckung, Lesen eines Berichts, warum bei 100 % Ab…
Artikel lesen →Datenbanken & SQLDELETE vs. TRUNCATE vs. DROP in SQL: Unterschiede, Rollback und Verwendungszweck
DELETE vs. TRUNCATE vs. DROP erklärt mit getestetem SQL: was jeweils entfernt wird, Rollback, Trigger, Identitätsrücksetzung, Geschwindigkeit und wi…
Artikel lesen →Datenbanken & SQLErklärte SQL-Ansichten: Erstellen, nutzen und vermeiden Sie Fallstricke mit Beispielen
SQL-Ansichten anhand der von uns ausgeführten Abfragen erklärt: Erstellen einer Ansicht, Live-Ergebnisse, Ausblenden von Spalten, Leistung, aktualis…
Artikel lesen →SoftwareentwicklungTypeScript-Schnittstelle vs. Typ: Echte Unterschiede, getestet mit dem Compiler
TypeScript-Schnittstelle vs. Typ, überprüft mit dem echten Compiler: Was beide können, was nur einer kann, Deklarationszusammenführung, Erweiterunge…
Artikel lesen →SoftwareentwicklungPython *args und **kwargs erklärt: Flexible Funktionen mit klaren Beispielen
Python *args und **kwargs erklärt mit Code, den wir ausgeführt haben: Packen und Entpacken, Parameterreihenfolge, Nur-Schlüsselwort- und Nur-Positio…
Artikel lesen →SoftwareentwicklungPython-Lambda-Funktionen: Syntax, tatsächliche Verwendung und wann man sie nicht verwendet
Python-Lambda-Funktionen erklärt mit Code, den wir ausgeführt haben: Syntax, Sortierung mit Schlüssel, Karte und Filter, Abschlüsse, die Late-Bindin…
Artikel lesen →Künstliche IntelligenzWas sind KI-Agenten? Wie sie funktionieren, mit einer einfachen Agentenschleife, die Sie ausführen können
Was sind KI-Agenten? Eine einfache Anleitung zur Agentenschleife, zu Tools, Speicher und Leitplanken, mit einer kleinen Python-Schleife, die wir aus…
Artikel lesen →DevOpsÜberwachung vs. Beobachtbarkeit: Der wahre Unterschied, mit Protokollen, Metriken und Traces
Überwachung vs. Beobachtbarkeit erklärt: bekannte und unbekannte Fehler, Protokolle, Metriken und Spuren, eine exemplarische Vorgehensweise für Chec…
Artikel lesen →DevOpsDocker-Volumes vs. Bind Mounts: Containerdaten auf die richtige Art und Weise beibehalten
Docker-Volumes vs. Bind-Mounts erklärt: Warum Containerdaten verschwinden, benannte Volumes, Bind-Mounts, tmpfs, Compose-Beispiele, Backups, Berecht…
Artikel lesen →TestautomatisierungTDD vs. BDD: Hauptunterschiede, eine Funktion, die auf beide Arten entwickelt wurde und wann sie jeweils verwendet werden sollte
TDD vs. BDD erklärt mit einer Rabattfunktion, die in beide Richtungen aufgebaut ist: Rot-Grün-Refaktor mit Code, den wir ausgeführt haben, Gegeben-W…
Artikel lesen →SoftwaretestsBenutzerakzeptanztests (UAT): Prozess, Checkliste und reale Beispiele
Benutzerakzeptanztests erklärt: Wer führt ihn durch, wie unterscheidet er sich von der Qualitätssicherung, ein siebenstufiger Prozess, eine UAT-Test…
Artikel lesen →Datenbanken & SQLErklärte SQL-NULL-Werte: IS NULL, COALESCE, NULLIF und die zu vermeidenden Fallen
SQL-NULL-Werte, die mit von uns ausgeführten Abfragen erklärt wurden: dreiwertige Logik, IS NULL, COALESCE, NULLIF, wie Aggregate, Joins und Sortier…
Artikel lesen →Datenbanken & SQLSQL CASE WHEN-Anweisung: Syntax, reale Beispiele und häufige Fehler
SQL CASE WHEN anhand der von uns ausgeführten Abfragen erklärt: einfache und durchsuchte Formulare, Bedingungsreihenfolge, Pivots mit SUM, COUNT-Tri…
Artikel lesen →SoftwareentwicklungWas ist JWT? JSON-Web-Tokens anhand eines funktionierenden Beispiels erklärt
Was ist JWT? JSON Web Tokens erklärt: die drei Teile, ein Token, das in dem von uns ausgeführten Code erstellt und manipuliert wurde, JWT vs. Sitzun…
Artikel lesen →SoftwareentwicklungErklärte JavaScript-Ereignisschleife: Aufrufstapel, Mikrotasks und Timer mit Beispielen
Die JavaScript-Ereignisschleife wurde mit dem von uns ausgeführten Code erklärt: Aufrufstapel, Aufgaben- und Mikrotask-Warteschlangen, warum setTime…
Artikel lesen →SoftwareentwicklungErklärung von Python-Generatoren und -Ertrag: Sparen Sie Speicher mit echten Beispielen
Python-Generatoren und Yield anhand des von uns ausgeführten Codes erklärt: wie sie angehalten und fortgesetzt werden, gemessene Speichereinsparunge…
Artikel lesen →Künstliche IntelligenzWas sind Einbettungen? Vektoren und Kosinusähnlichkeit einfach erklärt
Was sind Einbettungen? Ein Leitfaden in einfacher Sprache zu Vektoren, Kosinusähnlichkeit und semantischer Suche, mit einem kleinen Beispiel, das wi…
Artikel lesen →DevOpsBlau-Grün vs. Canary-Bereitstellung: Unterschiede, Kompromisse und Auswahl
Blue-Green vs. Canary-Bereitstellung erklärt: Funktionsweise, Kosten, Risiko und Rollback, stabiles Benutzer-Bucketing, das wir getestet haben, Date…
Artikel lesen →SoftwareentwicklungGit merge vs rebase: Unterschiede, Beispiele und wann man was nutzt
Git merge vs rebase erklärt mit echter Log-Ausgabe, einer Vergleichstabelle, der goldenen Regel des Rebase und einem sicheren Team-Workflow.
Artikel lesen →SoftwareentwicklungPython List Comprehension: Syntax, Beispiele und wann man darauf verzichtet
Python List Comprehension erklärt: Syntax, Filter, if-else, verschachtelte Schleifen, gemessene Zeiten und Fälle, in denen eine normale for-Schleife…
Artikel lesen →Datenbanken & SQLSQL Joins erklärt mit Beispielen (Inner, Left, Right, Full)
SQL Joins Schritt für Schritt mit Beispieltabellen und Abfragen verstehen: INNER, LEFT, RIGHT, FULL, CROSS und SELF, plus typische Fehler und Perfor…
Artikel lesen →