NULL in SQL ist seltsam
(jirevwe.github.io)-
In SQL werden NULL-Werte auf besondere Weise behandelt. Eine Spalte mit einer UNIQUE-Einschränkung kann mehrere NULL-Werte enthalten.
- Das liegt daran, dass jeder NULL-Wert als ein eigenständiger Wert betrachtet wird, der sich von jedem anderen NULL unterscheidet.
- SQLite, Postgres und MySQL verhalten sich dabei alle gleich.
-
Einen Maßstab festlegen
select '' = ''; -- Returns 1 (true) leere Zeichenketten sind gleich select 1 = 1; -- Returns 1 (true) Zahlen sind gleich select 1 = 0; -- Returns 0 (false) Zahlen sind verschieden select null = null; -- Returns NULL (null) Hä?- Das liegt daran, dass NULL ein Platzhalter für einen „unbekannten Wert“ ist und deshalb zwei unbekannte Werte nicht als gleich betrachtet werden.
- Mit dem
IS-Operator kann man die Identität von NULL prüfen. Zum Beispiel gibtnull is nullTRUE zurück.
-
Zur Eindeutigkeit
- Wenn eine Spalte mit einer UNIQUE-Einschränkung NULL-Werte enthält, werden diese NULL-Werte als verschieden behandelt und verletzen die Eindeutigkeitsbedingung daher nicht.
- Zum Beispiel werden
('ray@mail.com', NULL)und('ray@mail.com', NULL)als unterschiedliche Zeilen betrachtet.
-
Warum NULL so behandelt wird
- SQLite und andere SQL-kompatible Datenbanken sind so implementiert, um NULL konsistent mit anderen Datenbanken zu behandeln. Das SQL-Standarddokument legt nahe, dass NULL überall eindeutig sein sollte, aber in der Praxis behandeln die meisten SQL-Engines NULL bei
SELECT DISTINCToderUNIONnicht als eindeutig.
- SQLite und andere SQL-kompatible Datenbanken sind so implementiert, um NULL konsistent mit anderen Datenbanken zu behandeln. Das SQL-Standarddokument legt nahe, dass NULL überall eindeutig sein sollte, aber in der Praxis behandeln die meisten SQL-Engines NULL bei
-
Wie sich Eindeutigkeit sicherstellen lässt
-
Generierte Spalten verwenden
- Man kann das Problem abmildern, indem man eine Spalte erzeugt, die immer einen nicht-NULL-deterministischen Wert hat. Zum Beispiel kann man mit
COALESCE(deleted_at, '1970-01-01')NULL-Werte ersetzen. - Diese Methode kann zusätzlichen Platz belegen, weil sie der Tabelle ein weiteres Feld hinzufügt.
- Man kann das Problem abmildern, indem man eine Spalte erzeugt, die immer einen nicht-NULL-deterministischen Wert hat. Zum Beispiel kann man mit
-
Partielle Indizes verwenden
- Man kann einen partiellen Index auf
emailerzeugen, der nur gilt, wenndeleted_atNULL ist, um Eindeutigkeit sicherzustellen. - Partielle Indizes verbreitern die Tabelle nicht, benötigen weniger Speicherplatz und verursachen keine Fehler, wenn dasselbe Datensatzpaar wiederholt gelöscht wird.
- Man kann einen partiellen Index auf
-
-
Update
- Oracle behandelt leere Zeichenketten als NULL.
-
Fazit
- Bei der Verwendung eines ORM fällt es nicht auf, aber die besondere Behandlung von SQL-NULL kann zu Verwirrung führen. Das SQL-Standarddokument ist nicht frei verfügbar und nur gegen Bezahlung erhältlich.
2 Kommentare
Alle
null-Werte sind seltsam.Deshalb wirkt das völlig normale
nullin SQL eher so, als wäre es seltsam …Im Land der Einäugigen gilt der mit zwei Augen als unnormal …
Hacker-News-Kommentare
Das
NULLin SQL basiert auf der TRUE-FALSE-UNKNOWN-Logik von Kleene. Wenn manNULLals UNKNOWN liest, werden viele Operationen intuitiver verständlichNULList ein Platzhalter, der UNKNOWN darstellt, und man kann nicht sagen, dass zweiNULLgleich sindNULLS NOT DISTINCTeindeutige Indizes erzeugenAls das
NULL-Konzept in den 1970er-Jahren eingeführt wurde, dachte man, es würde in Zukunft viel Verwirrung stiften. Auch nach 45 Jahren wird noch immer darüber diskutiertIntuitives Verständnis von
NULL: DerNULL-Wert in einer bestimmten Tabellenzelle ist eine Methode, „kein Wert“ auszudrücken. Wenn man eindeutige Werte möchte, sollte man Fälle ohne Wert nicht berücksichtigenSkepsis gegenüber der Nutzung von ORMs: ORMs sind praktisch, aber es ist eine Generation entstanden, die nicht gelernt hat, wie relationale Datenbanken tatsächlich funktionieren. Das Verhalten von SQL-
NULLstimmt mit der grundlegenden relationalen Algebra überein, problematisch ist eherNULLim C-StilEs erinnert an den Humor rund um
NULL-Vergleiche in einem Dialog aus einer Blackadder-EpisodeIn Oracle wirkt es seltsam, dass
NULLmit einer leeren Zeichenkette gleichgesetzt wirdIm objektorientierten Kontext ist "null" nützlich, um auszudrücken, dass für eine bestimmte Eigenschaft kein Wert vorhanden ist. In JavaScript gibt es
nullundundefined; man kann annehmen, dassundefinedbedeutet, den Wert nicht zu kennen, währendnullbedeutet, dass kein Wert vorhanden istNULList nicht seltsam im Sinne von Duplikatfreiheit. WeilNULLeinander nicht gleich sind, können sie keine Duplikate sein. Wenn einem dieNULL-Semantik nicht gefällt, kann man Sentinel-Werte verwendenSQL-
NULList nicht seltsam, wenn man bedenkt, wie relationale Logik bei Datensätzen mit nicht existierenden Werten funktionieren soll