wake-up-neo.net

SQL: leere Zeichenfolge gegen NULL-Wert

Ich weiß, dass dieses Thema ein bisschen kontrovers ist und es gibt viele verschiedene Artikel/Meinungen im Internet. Leider gehen die meisten von ihnen davon aus, dass die Person nicht weiß, was der Unterschied zwischen NULL und leerer Zeichenfolge ist. Sie erzählen also Geschichten über überraschende Ergebnisse mit Joins/Aggregaten und machen im Allgemeinen etwas fortgeschrittenere SQL-Lektionen. Auf diese Weise verfehlen sie absolut den ganzen Punkt und sind daher für mich nutzlos. Hoffentlich bewegen diese Frage und alle Antworten das Thema ein wenig vorwärts.

Angenommen, ich habe eine Tabelle mit persönlichen Informationen (Name, Geburt usw.), in der eine der Spalten eine E-Mail-Adresse vom Typ varchar ist. Wir gehen davon aus, dass einige Personen aus irgendeinem Grund möglicherweise keine E-Mail-Adresse angeben möchten. Beim Einfügen solcher Daten (ohne E-Mail) in die Tabelle stehen zwei Optionen zur Verfügung: Setzen Sie die Zelle auf NULL oder setzen Sie sie auf eine leere Zeichenfolge (''). Nehmen wir an, ich kenne alle technischen Auswirkungen der Auswahl einer Lösung gegenüber einer anderen und kann für beide Szenarien korrekte SQL-Abfragen erstellen. Das Problem ist, dass beide Werte, selbst wenn sie sich auf technischer Ebene unterscheiden, auf logischer Ebene genau gleich sind. Nachdem ich mir NULL und '' angesehen hatte, kam ich zu einem einzigen Schluss: Ich kenne die E-Mail-Adresse des Mannes nicht. Egal wie sehr ich es auch versuchte, ich konnte keine E-Mail mit NULL oder einer leeren Zeichenfolge senden, daher stimmen anscheinend die meisten SMTP-Server meiner Logik zu. Also neige ich dazu, NULL zu verwenden, wenn ich den Wert nicht kenne und leere Zeichenfolgen als eine schlechte Sache betrachte.

Nach einigen intensiven Gesprächen mit Kollegen kam ich mit zwei Fragen:

  1. habe ich Recht, wenn ich davon ausgehe, dass die Verwendung einer leeren Zeichenfolge für einen unbekannten Wert dazu führt, dass eine Datenbank über die Fakten "lügt"? Genauer gesagt: Wenn ich die Idee von SQL verwende, was Wert ist und was nicht, kann ich zu dem Schluss kommen: Wir haben eine E-Mail-Adresse, nur indem wir herausfinden, dass sie nicht null ist. Aber später, wenn ich versuche, eine E-Mail zu senden, komme ich zu einem widersprüchlichen Schluss: Nein, wir haben keine E-Mail-Adresse, die @! # $ -Datenbank muss gelogen haben!

  2. Gibt es ein logisches Szenario, in dem eine leere Zeichenfolge '' ein so guter Träger wichtiger Informationen sein könnte (außer Wert und kein Wert), deren Speicherung auf andere Weise mühsam/ineffizient wäre (wie eine zusätzliche Spalte). Ich habe viele Beiträge gesehen, in denen behauptet wurde, dass es manchmal gut ist, leere Zeichenfolgen zusammen mit realen Werten und NULL-Werten zu verwenden, aber bisher kein logisches Szenario gesehen (in Bezug auf das SQL/DB-Design).

P.S. Einige Leute werden versucht sein zu antworten, dass es nur eine Frage des persönlichen Geschmacks ist. Ich stimme nicht zu Für mich ist es eine Designentscheidung mit wichtigen Konsequenzen. Daher würde ich gerne Antworten sehen, bei denen die Meinung dazu aus logischen und/oder technischen Gründen gestützt wird.

73
Jacek Prucia

Ich würde sagen, dass NULL die richtige Wahl für "keine E-Mail-Adresse" ist. Es gibt viele "ungültige" E-Mail-Adressen, und "" (leere Zeichenfolge) ist nur eine. Zum Beispiel ist "foo" keine gültige E-Mail-Adresse, "a @ b @ c" ist ungültig und so weiter. Nur weil "" keine gültige E-Mail-Adresse ist, ist dies kein Grund, sie als Wert "Keine E-Mail-Adresse" zu verwenden.

Ich denke, Sie haben Recht, wenn Sie sagen, dass "" nicht die richtige Art ist, "Ich habe keinen Wert für diese Spalte" zu sagen. "" is ein Wert.

Ein Beispiel dafür, wo "" ein gültiger Wert sein könnte, getrennt von NULL, könnte der zweite Vorname einer Person sein. Nicht jeder hat einen zweiten Vornamen, daher müssen Sie zwischen "kein zweiter Vorname" ("" - leere Zeichenfolge) und "Ich weiß nicht, ob diese Person einen zweiten Vornamen hat oder nicht" (NULL) unterscheiden. ). Es gibt wahrscheinlich viele andere Beispiele, bei denen eine leere Zeichenfolge immer noch ein gültiger Wert für eine Spalte ist.

84
Dean Harding

Während ich den obigen Kommentaren zustimme, möchte ich dieses Argument als Hauptmotivation hinzufügen:

  1. Für jeden Programmierer, der sich eine Datenbank ansieht, ist es offensichtlich, dass ein mit NULL gekennzeichnetes Feld ein optionales Feld ist. (d. h. der Datensatz benötigt keine Daten für diese Spalte)
  2. Wenn Sie ein Feld NICHT NULL markieren, sollte jeder Programmierer intuitiv davon ausgehen, dass es sich um ein erforderliches Feld handelt.
  3. In einem Feld, das Nullen zulässt, sollten Programmierer erwarten, dass Nullen anstelle von leeren Zeichenfolgen angezeigt werden.

Verwenden Sie zur Selbstdokumentation der intuitiven Codierung NULL anstelle von leeren Zeichenfolgen.

41
colinbashbash

In Ihrem Beispiel würde ich eine leere Zeichenfolge verwenden, wenn es sich um einen Wert direkt aus dem Webfeld handelt. Wenn der Benutzer angeben kann, dass er keine E-Mail bereitstellen oder löschen möchte, dann NULL.

Hier sind Links zu Punkten, die Sie berücksichtigen könnten: https://stackoverflow.com/questions/405909/null-vs-empty-when-dealing-with-user-input/405945#405945

--- bearbeitet (als Antwort auf Thomas Kommentar) ---

Datenbanken leben nicht ohne Anwendungen, die sie verwenden. Das Definieren von NULL oder '' hat keinen Wert, wenn die Anwendung es nicht richtig verwenden kann.

Stellen Sie sich ein Beispiel vor, in dem der Benutzer das LANGE Formular ausfüllt und die Eingabetaste drückt, um eine dauerhafte Anforderung an den Server zu senden. Er könnte gerade dabei sein, seine E-Mail einzugeben. Höchstwahrscheinlich möchten Sie alles, was er hat, im E-Mail-Feld speichern, damit er es später beenden kann. Was ist, wenn er nur einen Charakter eingegeben hat? Was ist, wenn er ein Zeichen eingegeben und dann gelöscht hat? Wenn keine E-Mail erforderlich ist, möchten Benutzer sie manchmal löschen. Dies ist der einfachste Weg, um nur das Feld zu löschen. Auch wenn keine E-Mail benötigt wird, lohnt es sich, diese vor dem Senden zu validieren.

Ein weiteres Beispiel: Benutzer geben E-Mails als spamto @ [bigcompany] .com an. In diesem Fall muss keine E-Mail gesendet werden, obwohl diese vorhanden und gültig ist (und möglicherweise sogar vorhanden ist). Das Senden einer solchen E-Mail ist vielleicht billig, aber wenn es 10.000 Benutzer mit solchen E-Mails für tägliche Abonnements gibt, kann eine solche Validierung viel Zeit sparen.

Verwenden Sie Null.

Es macht keinen Sinn, den Wert '' zu speichern, wenn Sie das Feld in der Tabelle einfach auf Null setzen. Es macht auch Abfragen offensichtlicher.

Welche SQL-Abfrage ist offensichtlicher und lesbarer, wenn Sie Benutzer mit einer E-Mail-Adresse finden möchten?

  1. SELECT * FROM Users WHERE email_address != ''

  2. SELECT * FROM Users WHERE email_address IS NOT NULL

  3. SELECT * FROM Users WHERE email_address != '' and email_address IS NOT NULL

Ich würde sagen 2 ist. Obwohl 3 in Fällen, in denen schlechte Daten gespeichert sind, robuster ist.

Für den Fall der E-Mail-Adresse auf dem Formular, die optional ist, sollte sie auch in der Tabelle angezeigt werden. In SQL ist es ein nullbares Feld, was bedeutet, dass es nicht bekannt ist.

Ich kann mir keinen vernünftigen geschäftlichen Wert vorstellen, wenn ich eine leere Zeichenfolge in einer anderen Tabelle als einfach schlechtem Design speichere. Es ist so, als würde man einen String-Wert von 'NULL' oder 'BLANK' speichern und Entwickler annehmen haben, dass er null oder ist eine leere Zeichenfolge. Für mich ist das schlechtes Design. Warum das speichern, wenn es NULL gibt?

Verwenden Sie einfach NULL und Sie werden alle ein bisschen glücklicher machen.

MEHR INFO:

SQL verwendet ein dreiwertiges Logiksystem: True, False und Unknown.

Für eine bessere und detailliertere Erklärung empfehle ich Entwicklern, Folgendes zu lesen: SQL-Abfragen - über TRUE und FALSE hinaus .

5
spong

Leider hat Oracle die Darstellung der VARCHAR-Zeichenfolge der Länge Null mit der Darstellung von NULL verwechselt. Sie werden beide intern durch ein einzelnes Byte mit dem Wert Null dargestellt. Dies macht die Diskussion noch viel schwieriger.

Ein Großteil der Verwirrung um NULL dreht sich um dreiwertige Logik. Betrachten Sie den folgenden Pseudocode:

if ZIPCODE = NULL
    print "ZIPCODE is NULL"
else if ZIPCODE <> NULL
    print "ZIPCODE is not NULL"
else print "Something unknown has happened"

Sie würden die dritte Nachricht nicht erwarten, aber genau das würden Sie unter drei bewerteten Logik erhalten. Drei geschätzte Logik führt Menschen zu zahlreichen Fehlern.

Eine weitere Quelle der Verwirrung ist das Ziehen von Schlussfolgerungen aus dem Fehlen von Daten, wie das Ziehen einer Schlussfolgerung aus dem Hund, der in der Nacht nicht bellte. Oft waren diese Schlussfolgerungen nicht das, was der Verfasser des NULL zu vermitteln beabsichtigte.

Trotzdem gibt es viele Situationen, in denen NULL das Fehlen von Daten problemlos handhabt und genau die gewünschten Ergebnisse liefert. Ein Beispiel sind Fremdschlüssel in optionalen Beziehungen. Wenn Sie mit NULL keine Beziehung in einer bestimmten Zeile angeben, wird diese Zeile wie erwartet aus einem inneren Join entfernt.

Beachten Sie auch, dass Sie, selbst wenn Sie NULLS in den gespeicherten Daten vollständig vermeiden (sechste Normalform), wenn Sie äußere Verknüpfungen durchführen, immer noch mit NULLS fertig werden müssen.

5
Walter Mitty

Ich denke, Dean Hardings Antwort deckt dies wirklich gut ab. Das heißt, ich möchte erwähnen, dass Sie, wenn Sie über NULL-Werte oder leere Zeichenfolgen auf DB-Ebene sprechen, über Ihre anderen Datentypen nachdenken sollten. Würden Sie das Mindestdatum speichern, wenn kein Datum angegeben ist? oder -1, wenn kein int angegeben ist? Wenn Sie einen Wert speichern, wenn Sie keinen Wert haben, müssen Sie eine ganze Reihe von Nichtwerten verfolgen. Mindestens eine für jeden Datentyp (möglicherweise mehr, wenn Sie Fälle erhalten, in denen -1 ein tatsächlicher Wert ist, sodass Sie eine Alternative usw. benötigen). Wenn Sie auf Anwendungsebene etwas "Fudgy" tun müssen/möchten, ist dies eine Sache, aber es ist nicht erforderlich, Ihre Daten zu verschmutzen.

5
bendemes

für die spezifische technische Frage ist das Problem nicht null gegenüber einer leeren Zeichenfolge, sondern ein Validierungsfehler. Eine leere Zeichenfolge ist keine gültige E-Mail-Adresse!

für die philosophische Frage ist die Antwort ähnlich: Validieren Sie Ihre Eingaben. Wenn eine leere Zeichenfolge ein gültiger Wert für das betreffende Feld ist, erwarten Sie ihn und codieren Sie ihn. Wenn nicht, verwenden Sie null.

Eine leere Zeichenfolge wäre eine gültige Eingabe, um die Frage zu beantworten: Was hat die Pantomime der Giraffe gesagt?

3
Steven A. Lowe

Ich könnte mir einen Grund für NULL und die leere Zeichenfolge vorstellen:

  • Sie haben gültige E-Mail-Adressen: [email protected]
  • Sie haben keine (und sollten wahrscheinlich nach einer fragen): NULL
  • Sie wissen, dass diese Person keine E-Mail-Adresse hat: Empty String.

Ich würde dies jedoch nicht empfehlen und ein separates Feld verwenden, um zu fragen, ob Sie wissen, dass keines vorhanden ist.

2
Marcel

Die Frage, wie ich es verstehe, ist, welche Interpretationen von NULL und leerer Zeichenfolge gewählt werden sollten. Dies hängt davon ab, in wie vielen Zuständen sich das jeweilige Feld befinden kann.

Die Interpretation hängt davon ab, wie auf die Datenbank zugegriffen wird. Wenn der Code eine Ebene enthält, die die Datenbank vollständig abstrahiert, ist es völlig akzeptabel, eine Richtlinie (einschließlich Zwei-Coulmn) auszuwählen, die funktioniert. (Es ist jedoch wichtig, die Richtlinie klar zu dokumentieren.) Wenn jedoch an mehreren Stellen auf die Datenbank zugegriffen wird, sollten Sie ein sehr einfaches Schema verwenden, da Code schwieriger zu warten ist und in diesem Fall möglicherweise fehlerhaft ist.

1
apoorv020

Grundsätzlich gibt es auf logischer Ebene keinen Unterschied zwischen "ungültigem" Wert und "keine Benutzereingabe", sie sind meistens nur "Sonderfälle". Fehlerfall.

Wenn Sie null haben, wird zusätzlicher Speicherplatz benötigt: Ceil (Spalten_mit_Null/8) in Bytes/pro Zeile.

Leere Zelle und Null sind beide Möglichkeiten, um zu markieren, dass etwas nicht stimmt/sollte Standard sein. Warum brauchen Sie 2 "falsche" Zustände? Warum NULL-Werte verwenden, wenn sie zusätzlichen Platz beanspruchen und genau dasselbe bedeuten wie leere Zeichenfolgen? Dies führt nur zu Verwirrung und Redundanz, wenn zwei Dinge genau dasselbe bedeuten (was bedeuten könnte). Es ist leicht zu vergessen, dass Sie NULL-Werte anstelle von leeren Zeichenfolgen verwenden sollten (wenn z. B. der Benutzer einige Felder ausgelassen hat).

Und Ihre Daten können zu einem Chaos werden. In einer perfekten Welt würde man sagen "die Daten werden immer korrekt sein und ich werde mich erinnern" ... aber wenn Leute in einem Team arbeiten müssen und nicht jeder genau auf Ihrem Niveau ist, ist es nicht ungewöhnlich zu sehen, WO (aa. xx <> '' AND bb.zz IS NOT NULL)

Anstatt meine Teammitglieder jeden zweiten Tag zu korrigieren, setze ich einfach einfache Regeln durch. Keine Nullwerte, NIE!

Das Zählen von NON-NULL-Werten ist schneller ... einfache Frage ist, wofür Sie das tun müssten?

1
Slawek

Ich neige dazu, es nicht aus der DB-Perspektive, sondern aus der Programmperspektive zu betrachten. Ich weiß, dass diese Frage für den SQL-Klick gilt, aber wie viele Benutzer greifen wirklich noch direkt auf Daten zu?

In einem Programm mag ich null/nichts nicht. Es gibt einige Ausnahmen, aber genau das sind sie. Und diese Ausnahmen sind wirklich nur schlechte Implementierungen.

Wenn der Benutzer die E-Mail nicht eingegeben hat, sollte etwas vorhanden sein, das bestimmt, ob dies gültig ist oder nicht. Wenn eine leere E-Mail in Ordnung ist, wird eine leere Zeichenfolge angezeigt. Wenn der Benutzer keine E-Mail eingegeben hat und dies gegen eine Regel verstößt, sollte das Objekt dies anzeigen.

Die Idee, dass Null keinen Sinn hat, ist alte Schule und etwas, woran moderne Programmierer arbeiten müssen.

Warum kann das E-Mail-Feld auch im DB-Design keine Nullen zulassen und eine Zeichenfolge mit der Länge Null sowie ein anderes Feld haben, das angibt, ob der Benutzer etwas eingibt? Ist ein bisschen so viel von einem DBMS zu verlangen? Die DB sollte meiner Meinung nach weder mit der Geschäftslogik noch mit der Anzeigelogik umgehen. Es wurde nicht dafür gebaut und macht es daher sehr schlecht.

1
ElGringoGrande