Gibt es einen zwingenden Grund, warum Spalten in SQL standardmäßig nullwertfähig sind?

8

Als CS-Student habe ich im Laufe der Jahre eine anständige Anzahl von Programmiersprachen gelernt, von denen die meisten das Konzept eines "nullbaren" oder "optionalen" Typs hatten. Beachten Sie, dass ich nicht über Nullzeiger oder Referenzen oder schwach typisierte Sprachen wie JavaScript spreche, in denen alles möglich ist null. Beispiele für das, worüber ich spreche, sind boost::optional(C ++), java.util.Optional(Java 8.0), prelude.Maybe(Haskell) und alle '?' Typen (zB int?, float?, C # und Kotlin). Dies sind Konstrukte, die einem zuvor nicht nullbaren Typ innerhalb eines strengen statischen Typsystems die Nullfähigkeit hinzufügen.

SQL hat ein ähnliches Konzept: Ein Typ INTEGER, der nullbar oder nicht nullbar gemacht werden kann - aber es gibt eine Wendung. In SQL INTEGERist standardmäßig nullwertfähig und muss explizit so geschrieben INTEGER NOT NULLwerden, dass es nicht nullwertfähig ist.

Es erscheint mir äußerst kontraintuitiv und potenziell gefährlich, wenn NULL als Standardverhalten zugelassen wird. Offensichtlich gibt es SQL zu diesem Zeitpunkt schon so lange, dass (die meisten) SQL-Entwickler ein gesundes Bewusstsein für die Fallstricke von NULL entwickelt haben. Aber ich kann mir nur vorstellen, dass sich NULL in den frühen Tagen oft an unerwarteten und problematischen Orten eingeschlichen hat.

SQL ist älter als alle Beispiele, die ich bereitgestellt habe, daher ist es möglich, dass dies nur eine Frage der historischen Entwicklung ist. Trotzdem muss ich fragen, ob es einen guten Grund gibt, die Sprache so zu gestalten, dass Typen standardmäßig auf Null gesetzt werden können.

Wenn ja, ist dies nur ein historischer Grund oder hält die Logik dem heutigen Datenbankdesign stand?

Bearbeiten: Ich frage nicht, warum NULL ein Teil von SQL ist oder warum nullbare Spalten nützlich sind. Ich frage nur, warum Spalten standardmäßig nullbar sind . Warum schreiben wir zum Beispiel:

column1 FLOAT,
column2 FLOAT NOT NULL

Eher, als:

column1 FLOAT NULLABLE,
column2 FLOAT
Annäherung an DarknessFish
quelle
2
Lernen Sie, diese Antwort zu akzeptieren: "Es gibt keinen Grund, es ist nur unsere Politik."
2
Denn manchmal muss das Konzept "Ich weiß nicht" klar in der Datenbank dargestellt werden
Newtopian
@Newtopian, das erklärt, warum NULL in der Sprache ist. Ich frage, warum NULL standardmäßig Spalten erlaubt ist.
Annäherung an
4
Weil "Ich weiß nicht" in Datenbankinformationen überraschend häufig vorkommt. Um diesen Punkt anhand eines Beispiels zu veranschaulichen. Stellen Sie sich Webformulare vor, in denen JEDE Felder standardmäßig obligatorisch sind und wie ärgerlich das wäre. In einer Datenbank MÜSSEN Sie JEDE Felder immer mit etwas füllen. In Ihrer Domain-Darstellung ist es jedoch sehr wahrscheinlich, dass viele dieser Informationen nicht unbedingt erforderlich sind und ohne negative Auswirkungen "unbekannt" bleiben können (vorausgesetzt, Sie schützen Ihren Code ordnungsgemäß). Tatsächlich würde ich wetten, dass in den meisten Anwendungen die meisten Informationen in diese nicht wesentliche Kategorie fallen, daher die Standardeinstellung
Newtopian
@ Newtopian In Ordnung. Geben Sie diese Antwort.
Annäherung an

Antworten:

24

An der Uni wurde mir beigebracht, dass das Gegenteil der Fall ist. Es ist viel gefährlicher, etwas not nullohne Grund zu machen . Bei einem nullbaren Feld ist das Schlimmste, was passieren kann, dass Sie über die Anwendung stolpern, die auf die Daten zugreift. Oh je, geh zurück und repariere die App ...

Mit einem Nicht-Null-Feld können Sie keine Datensätze hinzufügen, da kein beliebiges Feld verfügbar ist. Jetzt müssen Sie das Datenmodell ändern und möglicherweise das Ergebnis an vielen verschiedenen Stellen korrigieren ...

Es ist gut, sich null"unbekannt" vorzustellen. Wenn es einen plausiblen Grund gibt, warum Sie einen Datensatz eingeben möchten, ohne etwas zu wissen, sollte er nullwertfähig sein.

Einer meiner Universitätsdozenten hat es so beschrieben:

Apokryphisch habe ich von einem Verkaufssystem in den USA gehört, für dessen Verkauf die Sozialversicherungsnummer des Kunden erforderlich war. Alle Kassenbetreiber, die es taten, als ein Ausländer zur Kasse kam, gaben 000-00-0000 ein. Aber dann würden andere 123-45-6789 eingeben. Dies macht es unmöglich, Müll zu identifizieren. Es ist viel besser, ein Feld leer zu lassen, als es zu zwingen, Junk zu enthalten.

Oder eine andere Geschichte. Mir wurde die Kfz-Versicherung wirklich verweigert, weil ich keine zwei Telefonnummern habe. Sie würden mich absolut nicht versichern, wenn ich ihnen nicht zwei geben würde. Der Verkäufer schlug vor, ich gebe nur eine falsche. Am Ende weigerte ich mich, einen Versicherer anzulügen und ging einfach mit einer anderen Firma.

In der Praxis Reserve not nullfür Felder, die erforderlich sind, um die Aufzeichnung zu verstehen. Zum Beispiel:

Eine Tabelle mit Orten mit Feldern (ID, Ortsname, Land, Längengrad, Breitengrad) ... "Längengrad" "Breitengrad" sollte nullwertfähig sein, damit Sie die Existenz eines Ortes speichern können, bevor Sie wissen, wo er sich befindet.

Wenn Sie jedoch eine Tabelle haben, deren einziger Zweck darin besteht, geografische Coodinaten mit Feldern (Item_id, Längengrad, Breitengrad) zu speichern, ist der gesamte Datensatz bedeutungslos, wenn Längen- und Breitengrad Null sind. Daher sollten sie in diesem Fall nicht null sein

Nach meiner Berufserfahrung seit der Uni gibt es weit mehr Bereiche, die optional sein können, als obligatorisch sein müssen.

Philip Couling
quelle
Wen zitieren Sie im obigen Zitatblock?
Robert Harvey
Hochschullehrer.
Philip Couling
8

Es kommt mir äußerst kontraintuitiv vor ...

Intuitiv ist im Auge des Betrachters und Ihre Meinung dazu wird durch die Dinge geprägt, denen Sie ausgesetzt waren. Ich komme aus einer Zeit, in der diese Art von Sicherheit nicht Standard war und die Werkzeuge nicht darauf hinwiesen, wann Sie vermasselt haben. Ich habe die Kettensäge lange genug ohne Klingenschutz verwendet, sodass mein erster Instinkt darin besteht, die Intuition vollständig zu vermeiden, zur DDL zurückzukehren und genau herauszufinden, welche Annahmen das Schema über die Daten machen wird.

... und möglicherweise gefährlich, wenn NULL als Standardverhalten zugelassen wird.

Ich denke, Sie übertreiben die relativen Gefahren. NOT NULLhat seine eigenen Fallstricke, die zu ebenso heimtückischen Fehlern führen können. (Ihre Aufzählung wäre das Futter für eine andere Frage.)

Der Designer einer Tabelle hat immer die Möglichkeit, eine Spalte NULLeinzuschränken, NOT NULLund wird das eine oder andere tun, um die Standardeinstellung zu umgehen, unabhängig davon, um was es sich handelt. Wenn eine Spalte nicht korrekt eingeschränkt wird, befolgt ein Entwickler die Geschäftsregeln nicht. Wenn Entwickler aufgrund der Definition der Spalte an anderer Stelle nicht das Richtige tun, kann er die Daten, die ihm übergeben werden, nicht verstehen. Es gibt auch keine technische Lösung.

Trotzdem muss ich fragen, ob es einen guten Grund gibt, die Sprache so zu gestalten, dass Typen standardmäßig auf Null gesetzt werden können.

Nein, gibt es nicht. Da beide Gefahren bergen, gibt es auch keinen guten Grund, die Sprache anders zu gestalten. Es läuft darauf hinaus, Ihr Gift zu pflücken.

Blrfl
quelle
6

In SQL sind nullbare Spalten aufgrund äußerer Verknüpfungen erforderlich (auch als linke Verknüpfungen oder rechte Verknüpfungen bezeichnet). Wenn die Zeile auf einer Seite des Joins auf der anderen Seite nicht übereinstimmt, müssen die Felder für die andere Seite NULL-Werte enthalten. Da die Ausgabe eines Joins nullfähige Spalten haben kann, sollten Basistabellen diese aufgrund des Prinzips des relationalen Abschlusses ebenfalls unterstützen (die im Grunde angeben, dass das Ergebnis einer Abfrage oder Ansicht nicht von einer Basistabelle zu unterscheiden ist).

Vor diesem Hintergrund muss SQL nullfähige Spalten unterstützen. Auf der anderen Seite sind nicht nullfähige Spalten eine sekundäre Funktion - SQL könnte auch ohne sie funktionieren.

JacquesB
quelle
4

Lassen Sie es uns umdrehen und sagen, dass Sie Recht haben. Angenommen, Ihre Ganzzahl ist standardmäßig nicht null.

Das heißt, es muss standardmäßig einen Wert haben. Auch wenn es nicht bekannt ist.

Wenn Sie also Ihre Personentabelle aktualisieren und entweder zwei Möglichkeiten haben: Es ist unmöglich, die Tabelle zu aktualisieren, da Sie kein Gewicht eingegeben haben. Oder wenn Sie das Gewichtsargument nicht angegeben haben, wird es in den Standard "-1 Kilo" eingegeben, wenn es unbekannt ist.

Beide Situationen sind unerwünscht. Sie möchten Kunden hinzufügen können, auch wenn Sie deren Gewicht nicht kennen. Sie möchten aber auch keine "Proxy" -Werte haben. Werte, die Platzhalter sind, aber eine echte Bedeutung haben können, zum Beispiel: können in mathematischen Funktionen wie "Durchschnitt" verwendet werden, sind aber keine echten Werte.

Ich meine, bei der Berechnung eines Durchschnittsgewichts ist -1 ein gültiger Wert in Ihrer mathematischen Durchschnittsfunktion, aber nicht als Personengewicht. Sie verwenden null und jetzt weiß Ihre durchschnittliche Funktion, diesen Wert zu ignorieren.

Außerdem würde ich SQL nicht wirklich mit Programmiersprachen vergleichen, wenn ich über Nullen diskutiere. Sie sind von Natur aus unterschiedlich. Null in SQL ist ein wesentlicher Bestandteil der Theorie des relationalen Datenbankdesigns.

Pieter B.
quelle
3

Nein. Es gibt keinen zwingenden Grund, warum SQL standardmäßig nullable ist. Tatsächlich haben viele prominente Forscher in der relationalen Datenbanktheorie dieser Entwurfsentscheidung widersprochen, vielleicht vor allem Chris Date , ein häufiger Mitarbeiter des ursprünglichen Designers der relationalen Datenbank, Edgar Codd . Date (zusammen mit Co-Autor Hugh Darwen) veröffentlichte ein bekanntes Buch über relationale Theorie (" The Third Manifesto "), das Prinzipien für alternative Designs für eine Familie relationaler Sprachen beschreibt, die sie "D" nennen, sowie ein Beispiel für eine solche Sprache namens "D". Tutorial D ".

D-Sprachen dürfen NULL-Werte nicht ausdrücklich unterstützen ("D darf kein Konzept einer" Beziehung "enthalten, in der ein" Tupel "ein" Attribut "enthält, das keinen Wert hat."). Stattdessen werden optionale Werte durch alternative Datentypen unterstützt, die Ortsmarker "nicht vorhanden" oder ähnliche Werte enthalten. D-Sprachen bieten ein umfangreiches Modell für benutzerdefinierte Typen, mit dem jeder native Typ um solche zusätzlichen Werte erweitert werden kann.

Es gibt überzeugende theoretische Gründe, warum dies eine gute Idee ist, und Date & Darwen haben viel darüber und über die anderen Entscheidungen, die sie in ihrem Design getroffen haben, geschrieben. Ich empfehle dringend, ihre Arbeit zu diesem Thema zu lesen.

Jules
quelle
1
Ich folge deiner Logik nicht / stimme ihr nicht zu. Ich glaube, Sie verschmelzen zwei verschiedene Themen. Problem a) Sollte eine Sprache überhaupt null darstellen? Problem b) In einer Sprache, in der null "nicht vorhanden" bedeutet, sollten Felder standardmäßig null (nicht vorhanden) zulassen? Vielleicht haben Sie einen Schritt in Ihrer Antwort verpasst ... Gibt es einen Punkt? C) In D dürfen Attribute standardmäßig keine Nicht-Anwesenheit zulassen, weil ... <Argument hier einfügen>
Philip Couling
2
Mein erster Kommentar ist schwer zu folgen, deshalb werde ich es einfach sagen: Representing x with null is a bad ideaSchliesst nicht darauf allowing x by default is bad. Ergo bedeutet das nicht, dassallowing null by default is bad where null is the only available representation of x
Philip Couling
1
@jules Was ist der konzeptionelle Unterschied zwischen einem int-Feld, das nullbar ist, und einem int-Feld mit einem alternativen Datentyp: 'nicht vorhanden'? Ist es nicht dasselbe mit einem anderen Namen? Null ist auch ein alternativer Datentyp zu int.
Pieter B
1
@PieterB Ja und nein. Das grundlegende Problem von Null ist, dass es verwendet wird, um zu viele verschiedene Dinge zu bedeuten. In SQL könnte es bedeuten "existiert nicht" oder es könnte "unbekannt" bedeuten. Das D-Argument ist, dass diese alle eindeutig definiert sein sollten und niemals ein Sammelbegriff "null" verwendet werden sollte. Nachdem ich es nicht im Detail studiert habe, vermute ich, dass Befürworter von D befürworten würden, Not Present = Not Presentwo in SQL weder noch null = nulloder null != nullwahr sind.
Philip Couling
Codd sagte, dass es mehr Arten von Null geben sollte. Ich denke, er schlug zunächst 4 vor und erweiterte sie später auf 17. Programmierer sagten: Warum verschwenden wir Mühe, um zu unterscheiden, wie man "Ich weiß nicht" sagt? Sicher, es gibt bekannte Unbekannte und unbekannte Unbekannte, aber tatsächlich sind Daten die bekannten bekannten und nicht viel anderes.
1

Ich bin nicht anderer Meinung als Ihre Prämisse, wie die Standardeinstellung lauten soll, aber es ist eine gute Praxis, als Entwickler nichts anzunehmen. Das Überprüfen der Spezifikationen in einer Datenbanktabelle sollte nicht allzu schwierig sein.

Aus DBA-Sicht, bei der Sie insbesondere beim Zusammenführen von anderen Systemen aufgefordert werden, Daten in großen Mengen zu laden, sollten Sie die Einstellungen für jedes Feld besser kennen, unabhängig davon, ob Sie Daten in das Feld einfügen müssen oder nicht.

Unternehmen und Anwendungen werden von Menschen betrieben. Wenn sie kein Programmierer sind, sind die Definitionen von "nie" und "immer" nicht genau gleich und ändern sich im Laufe der Zeit. Die aktuelle Null-Einstellung für ein bestimmtes Feld sollte nicht unscharf sein.

JeffO
quelle
Richtig, Massenlast, Migration usw. sind letztendlich wichtiger als alle anderen Probleme, da die Daten real und wertvoll sind und Programme nur temporäre Werkzeuge sind, die sie prägen. Hat jemand eine Lochkarte oder die Aufzeichnungsgeräte aus der Volkszählung von 1900 gesehen? Nein, aber die Daten sind noch verfügbar. Wie oft wurde es sogar im letzten Jahr von einem System auf ein anderes verschoben? Jedes Mal, wenn jemand es benutzt, nehme ich an.
0

Datenbanken unterscheiden sich von normalen Programmiersprachen.

Da das Schema einer Tabelle festgelegt ist, müssen beim Speichern der Informationen in einer Zeile alle Daten vorhanden sein. Viele dieser Daten sind jedoch möglicherweise nicht erforderlich, um eine gültige Darstellung eines Modellobjekts zu erstellen, sobald es in Ihren Code geladen wurde. Das Erfordernis, dass alle Daten nicht null sein und ausgefüllt werden müssen, bedeutet, dass diese nicht erforderlichen Felder einen Wert enthalten müssen und noch keinen haben. Sie sind "unbekannt".

Stellen Sie sich vor, Sie müssen die ganze Zeit ALLE Felder in Webformularen ausfüllen, da sie in der Datenbank nicht null sein dürfen. Sie müssen einen Wert erhalten ... ein Rezept für Wahnsinn!

Sie können einige reservierte Werte festlegen, um das Fehlen von Daten, eine leere Zeichenfolge, eine bestimmte Nummer, ein bestimmtes Datum usw. abhängig vom Datentyp darzustellen. Welchen Wert wählen Sie jedoch aus? Dann müssen Sie sicherstellen, dass alle zustimmen, dass diese willkürlichen Werte tatsächlich "unbekannt" und nicht beispielsweise "1. Januar 1970" bedeuten. Null-Abneigung kann viele Formen annehmen und Sie auf lange, verschlungene Umwege führen, nur weil jemand sagte, Nullen seien schlecht. Wie komplex sind Sie bereit, nur um den Umgang mit Nullen zu vermeiden?

Ich habe einen einzigen universellen Wert für alles Unbekannte und finde es viel besser, einen Satz beliebiger konstanter Werte zu verwenden. Ich sage nicht, dass konstante Werte schlecht und null besser sind. Wenn Ihr Modell durch eine Konstante zur Darstellung dieser Informationen gut bedient wird, verwenden Sie diese auf jeden Fall, aber es gibt viele Situationen, in denen eine Null genau das ist, was am besten passt. Für alle Nullhasser ist dies eine Situation, in der Null erfunden werden müsste, wenn Null verweigert würde!

Wenn man sieht, wie weit verbreitet das Konzept "unbekannt" in einer Datenbank ist, dann würde ich sagen, dass es sehr sinnvoll ist, die Werte auf Null zu setzen.

Wenn ich hier tiefer gehe und andere Antworten betrachte, wäre ich nicht überrascht zu erfahren, dass Nullen nicht nur ein "Sprachmerkmal" sind, sondern ein wesentlicher Bestandteil der zugrunde liegenden Theorie, auf der SQL basiert. Man kann C (die Lichtgeschwindigkeit) aus der Relativitätstheorie entfernen, aber das Konzept der absoluten Höchstgeschwindigkeit bleibt bestehen und muss immer noch ausgedrückt werden, damit es in irgendeiner Form zurückkehrt.

Newtopian
quelle
0

Kurze Antwort: Abwärtskompatibilität.

Lange Antwort:

In einer vollständig normalisierten Datenbank ist NULL in keiner Spalte zulässig. Angenommen, es gibt eine Tabelle namens MailingAddress mit einer Spalte PostOfficeBox, die eine Ganzzahl ist. Da nicht jeder ein Postfach hat, gibt es zwei Möglichkeiten, dies umzusetzen.

Erstens könnte NULL in der Spalte erlaubt sein.

Zweitens wird PostOfficeBox aus MailingAddress entfernt und eine neue Tabelle erstellt. PostOfficeBox wird mit einer Spaltennummer erstellt, deren PK die FK für MailingAddress ist. Jetzt sind zwei Abfragen erforderlich, um Postanschriften zu erhalten: eine für diejenigen ohne Postfach und eine für diejenigen mit.

SQL erlaubt aus praktischen Gründen NULL-Werte in Spalten.

shawnhcorey
quelle