Wann sollte NULL und wann eine leere Zeichenfolge verwendet werden?

82

Ich interessiere mich hauptsächlich für MySQL und PostgreSQL, aber Sie könnten im Allgemeinen Folgendes beantworten:

  • Gibt es ein logisches Szenario, in dem es nützlich wäre, eine leere Zeichenfolge von NULL zu unterscheiden?
  • Welche Auswirkungen hätte der physische Speicher auf das Speichern einer leeren Zeichenfolge als ...

    • NULL?
    • Leerer String?
    • Ein anderes Feld?
    • Irgendwie anders?
Maniero
quelle

Antworten:

67

Angenommen, der Datensatz stammt aus einem Formular zum Erfassen von Name- und Adressinformationen. Zeile 2 der Adresse ist normalerweise leer, wenn der Benutzer nicht in der Wohnung wohnt. Eine leere Zeichenkette ist in diesem Fall vollkommen gültig. Ich bevorzuge die Verwendung von NULL, um anzuzeigen, dass der Wert unbekannt oder nicht angegeben ist.

Ich glaube nicht, dass es sich lohnt, sich in der Praxis über den Unterschied bei der physischen Speicherung Gedanken zu machen. Als Datenbankadministratoren haben wir viel größere Fische zum Braten!

Larry Coleman
quelle
2
Sehr wenige DBAs müssen sich jemals Gedanken über die Geschwindigkeits- / Größenunterschiede bei der Verwendung von machen NULLoder nicht
Patrick
28
Einverstanden ... Ich versuche, NULL für "nicht bekannt" zu reservieren ... leere Zeichenfolge ist "wir wissen, dass es leer sein sollte". Dies ist besonders nützlich, wenn Ihre Daten aus mehreren Quellen stammen
Joe
6
Hervorragend - NULL ist nicht bekannt, leere Zeichenfolge wurde angegeben.
ScottCher
@ Larry, wie wirkt sich das auf die Leistung aus? Wie variiert die Leistung bei Tabellen mit vielen Spalten gegenüber Tabellen mit vielen Zeilen?
Shimmy
Ich bin damit einverstanden, dass wenn es in Ihrem Datensatz einen Unterschied zwischen keinem angegebenen Wert und einer leeren Zeichenfolge gibt, Sie diese angemessen verwenden sollten. Wenn ich diese Unterscheidung bei meinen Daten nicht benötige, verwende ich immer eine leere Zeichenfolge, nur weil ich Stellen Sie fest, dass das Abfrageergebnis eines MySQL-Clients in der Befehlszeile übersichtlicher ist, wenn leere Zeichenfolgen anstelle vieler NULL-Werte verwendet werden
RTF
25

Ich weiß nichts über MySQL und PostgreSQL, aber lassen Sie mich das etwas allgemein behandeln.

Es gibt ein DBMS, nämlich Oracle, bei dem die Benutzer nicht zwischen NULL und '' ausgewählt werden können. Dies zeigt deutlich, dass nicht zwischen beiden unterschieden werden muss. Es gibt einige ärgerliche Konsequenzen:

Sie setzen ein varchar2 auf eine leere Zeichenfolge wie folgt:

Update mytable set varchar_col = '';

Das Folgende führt zum gleichen Ergebnis

Update mytable set varchar_col = NULL;

Um jedoch die Spalten auszuwählen, in denen der Wert leer oder NULL ist, müssen Sie verwenden

select * from mytable where varchar_col is NULL;

Verwenden

select * from mytable where varchar_col = '';

ist syntaktisch korrekt, gibt aber niemals eine Zeile zurück.

Auf der anderen Seite, wenn Sie Zeichenfolgen in Oracle verketten. NULL-Varchars werden als leere Zeichenfolgen behandelt.

select NULL || 'abc' from DUAL;

ergibt abc . Andere DBMS würden in diesen Fällen NULL zurückgeben.

Wenn Sie explizit ausdrücken möchten, dass ein Wert zugewiesen ist, müssen Sie so etwas wie "" verwenden.

Und Sie müssen sich Sorgen machen, ob das Zuschneiden nicht zu NULL führt

select case when ltrim(' ') is null then 'null' else 'not null' end from dual

Es tut.

Betrachtet man nun DBMS, bei dem '' nicht mit NULL identisch ist (zB SQL-Server)

Die Arbeit mit '' ist im Allgemeinen einfacher und in den meisten Fällen besteht keine praktische Notwendigkeit, zwischen beiden zu unterscheiden. Eine der Ausnahmen, die ich kenne, ist, wenn Ihre Spalte eine Einstellung darstellt und Sie keine leeren Standardeinstellungen für sie haben. Wenn Sie zwischen '' und NULL unterscheiden können, können Sie ausdrücken, dass Ihre Einstellung leer ist, und vermeiden, dass die Standardeinstellung angewendet wird.

bernd_k
quelle
17

Dies hängt von der Domain ab, an der Sie arbeiten. NULLbedeutet, dass kein Wert vorhanden ist (dh es gibt keinen Wert ), während leere Zeichenfolge bedeutet, dass ein Zeichenfolgenwert mit der Länge Null vorhanden ist.

Angenommen, Sie haben eine Tabelle zum Speichern der Daten einer Person und sie enthält eine GenderSpalte. Sie können die Werte als 'Männlich' oder 'Weiblich' speichern. Wenn der Benutzer auswählen kann, dass die Geschlechtsdaten nicht angegeben werden sollen, sollten Sie diese als NULL(dh Benutzer hat den Wert nicht angegeben) und nicht als leere Zeichenfolge speichern (da es kein Geschlecht mit dem Wert '' gibt).

Gan
quelle
7
Wenn der Benutzer kein Geschlecht angegeben hat, sollten Sie "Abgelehnt" speichern. NULL ist nicht eindeutig. es könnte auch bedeuten "der Kunde wurde nicht gefragt", "der Kunde identifiziert sich mit einem Geschlecht, das nicht auf unserer Liste steht" usw.
Jon of All Trades
8

Beachten Sie, dass Sie leere Werte als NULL speichern müssen, wenn Sie ein Feld haben, das nicht erforderlich ist, aber alle vorhandenen Werte eindeutig sein müssen. Andernfalls können Sie nur ein Tupel mit einem leeren Wert in diesem Feld haben.

Es gibt auch einige Unterschiede zur relationalen Algebra und zu NULL-Werten: NULL! = NULL, zum Beispiel.

Matthew Schinckel
quelle
4
NULL! = NULL ist eigentlich nicht der Fall, denn das ist NULL. ;-)
Peter Eisentraut
1
Beachten Sie, dass MS SQL diese Regel nicht befolgt: Mehrere NULL-Werte verletzen eine UNIQUEEinschränkung. Glücklicherweise können Sie ab 2008 einen gefilterten Index verwenden, um das richtige Verhalten zu erzielen.
Jon of All Trades
4

Ein neuer Gedanke, ein großer Einfluss auf Ihre Wahl von NULL/ NOT NULList, wenn Sie ein Framework verwenden. Ich verwende viel Symfony und die Verwendung von Erlaubnisfeldern NULLvereinfacht einige der Code- und Datenprüfungen bei der Bearbeitung der Daten.

Wenn Sie kein Framework verwenden oder einfache SQL-Anweisungen und -Verarbeitungen verwenden, würde ich mich für die Wahl entscheiden, die Sie für einfacher halten, den Überblick zu behalten. Ich bevorzuge im Allgemeinen NULL, damit es bei der INSERTAusführung von Anweisungen nicht langweilig wird, die leeren Felder auf zu setzen NULL.

Patrick
quelle
Die Frage ist NULL vs. leere Zeichenkette (in einer nullbaren Spalte, IMO), nicht NULL vs. NOT NULL, nicht wahr?
Gan
Der Teil der Frage nach dem Speicher hat mich zu der Annahme veranlasst, dass er möglicherweise auch über Null / Not Null nachdenkt
Patrick
oder @jeder andere bezüglich der Implikation von NULL vs NOT NULL, Sie können sich darauf beziehen: dba.stackexchange.com/q/63/107
Gan
2

Nachdem ich mit Oracle arbeiten musste ( was keine Unterscheidung zulässt ), bin ich zu folgendem Schluss gekommen:

  • Aus einem logischen POV ist es egal. Ich kann mir wirklich kein überzeugendes Beispiel vorstellen, bei dem die Unterscheidung zwischen NULL und einem String mit der Länge Null dem DBMS einen Wert hinzufügt.

  • Hieraus folgt: Sie haben entweder eine NULLSpalte, in der Nullen nicht zulässig sind ''(Oracle-ish-Lösung), oder eine NOT NULLSpalte, in der Nullen zulässig sind.

  • Und meiner Erfahrung nach ''ist es viel sinnvoller, wenn Sie die Daten verarbeiten, da Sie normalerweise das Fehlen einer Zeichenfolge als leere Zeichenfolge verarbeiten möchten: Verkettung, Vergleich usw.

Hinweis: So kehren Sie zu meiner Oracle-Erfahrung zurück: Angenommen, Sie möchten eine Abfrage für eine Suchanfrage generieren. Wenn Sie verwenden '', können Sie nur generieren WHERE columnX = <searchvalue>und es wird für die Suche nach Gleichheit funktionieren. Wenn Sie verwenden NULL, müssen Sie tun WHERE columnX=<searchvalue> or (columnX is NULL and serchvalue is NULL). Bah! :-)

Martin
quelle
2

Sie unterscheiden sich auch aus gestalterischer Sicht:

z.B

CREATE TABLE t (
    id INTEGER  NOT NULL,
    name CHARACTER(40),
    CONSTRAINT t_PK PRIMARY KEY (id)
);

CREATE UNIQUE INDEX t_AK1 ON t (name);

Sieht aus wie:

 \d t
          Table "public.t"
 Column |     Type      | Modifiers
--------+---------------+-----------
 id     | integer       | not null
 name   | character(40) |
Indexes:
    "t_pk" PRIMARY KEY, btree (id)
    "t_ak1" UNIQUE, btree (name)

Lass uns ein paar Daten einfügen:

op=# insert into t(id, name ) values ( 1, 'Hello');
INSERT 0 1

op=# insert into t( id, name) values ( 2, '');
INSERT 0 1

op=# insert into t( id, name) values ( 3, '');

ERROR:  duplicate key value violates unique constraint "t_ak1"

Versuchen wir es jetzt mit null:

op=# insert into t( id, name) values (4, null );

INSERT 0 1

op=# insert into t( id, name) values (5, null);

INSERT 0 1

Das ist erlaubt.

Soooooo: Nullen sind weder triviale Zeichenfolgen noch das Gegenteil.

Prost

Guy Birkbeck
quelle
1

Wenn wir über Theorie sprechen, dann besagen die Codd-Regeln, dass RDBMS NULLWerte auf besondere Weise behandeln muss .

Wie genau das verwendet wird, hängt von den Datenbankarchitekten ab, abhängig vom tatsächlichen Gebiet - Aufgabe - Projekt - Anwendungsbereich.

noonex
quelle