Nullable Foreign Key schlechte Praxis?


114

Angenommen, Sie haben eine Tabelle Bestellungen mit einem Fremdschlüssel für eine Kunden-ID. Angenommen, Sie möchten eine Bestellung ohne Kunden-ID hinzufügen (ob dies möglich sein sollte, ist eine andere Frage). Sie müssten den Fremdschlüssel auf NULL setzen. Ist das eine schlechte Praxis oder möchten Sie lieber mit einer Verknüpfungstabelle zwischen arbeiten Bestellungen und Kunden? Obwohl die Beziehung 1 zu n ist, würde eine Verknüpfungstabelle sie zu n zu n machen. Andererseits habe ich mit einer Link-Tabelle diese NULL-Werte nicht mehr ...

Die Datenbank enthält nicht viele NULL-Werte, da ein Datensatz mit einem Fremdschlüssel für NULL nur vorübergehend erstellt wird, bis ein Kunde für die Bestellung hinzugefügt wird.

(In meinem Fall ist es keine Bestellung und kein Kunde).

EDIT: Was ist mit einem nicht zugewiesenen Kunden, zu dem ein Link erstellt werden soll?


9
Dies ist einer der Hauptzwecke, wenn NULL-Werte in einem Datenbankschema verfügbar sind. Außerdem können Sie deshalb die Felder NULL oder NOT NULL deklarieren, damit die spezifischen Anforderungen Ihres Schemas erfüllt werden können.
Gahooa

7
Ich las die Frage zunächst als Nullable Primary Keys und wollte gerade mit einigen starken Ratschlägen einsteigen ... :-)
Andrzej Doyle

Antworten:


51

Die Link-Tabelle ist wahrscheinlich eine bessere Option. Zumindest verstößt es nicht gegen die Normalisierung BCNF (Boyce-Codd Normalform). Ich würde es jedoch vorziehen, pragmatisch zu sein. Wenn Sie nur sehr wenige dieser Nullwerte haben und diese nur vorübergehend sind, sollten Sie die Verknüpfungstabelle überspringen, da dies das Schema nur komplexer macht.

Als Randnotiz; Die Verwendung einer Verknüpfungstabelle führt nicht unbedingt zu n zu n. Wenn Sie in der Verknüpfungstabelle den Fremdschlüssel verwenden, der auf Ihre Auftragstabelle als Primärschlüssel in dieser Verknüpfungstabelle verweist, ist die Beziehung immer noch 1..n. Pro Bestellung kann es nur einen Eintrag in dieser Verknüpfungstabelle geben.


2
source__destination_link oder SourceDestination
Svisstack

7
Ich würde gerne etwas über eine Situation erfahren, in der es besser ist, eine Verknüpfungstabelle zu haben. Ich bin nie auf eine Situation gestoßen, in der dies den Prozessfluss in irgendeiner Weise verbessert hätte.
Reimius

5
Wie in meiner Antwort ausgeführt, wäre ich in diesem speziellen Fall pragmatisch und würde keine Verknüpfungstabelle verwenden. Ich bin sicher, dass die normalen Formen nicht erfunden wurden, um den Prozessfluss zu verbessern, sondern um Konsistenz zu gewährleisten und Redundanz zu vermeiden. Es ist jedoch eine sehr allgemeine Diskussion, ich denke, sie muss von Fall zu Fall betrachtet werden.
Patrik Hägne

110

Nein Mit Nullable FKs ist nichts falsch. Dies ist häufig der Fall, wenn die Entität, auf die der FK zeigt, in einer Beziehung (null oder eins) zu (1 oder viele) mit der Primärschlüssel-Referenztabelle steht.

Ein Beispiel könnte sein, wenn Sie sowohl eine physikalische Adresse als auch ein Postanschriftattribut (Spalte) in einer Tabelle mit FKs zu einer Adresstabelle hatten. Sie können festlegen, dass die physische Adresse auf Null gesetzt werden kann, wenn die Entität nur über ein Postfach (Postanschrift) verfügt, und dass die Postanschrift auf Null gesetzt werden kann, wenn die Postanschrift mit der physischen Adresse übereinstimmt (oder nicht).


37

Nullable-Spalten können in 1NF bis 5NF sein, aber nicht in 6NF, wie ich gelesen habe.

Nur wenn Sie besser als Chris Date wissen, "was die erste normale Form wirklich bedeutet". Wenn x und y beide nullwertfähig sind und tatsächlich in einer Reihe x und y beide sind null, WHERE x=yergibt sich nichts true. Dies beweist zweifelsfrei, dass null kein Wert ist (weil jeder reale Wert immer gleich sich selbst ist). Und da der RM vorschreibt, dass "in jeder Zelle einer Tabelle ein Wert vorhanden sein muss", ist alles, was möglicherweise Nullen enthält, keine relationale Sache, und daher stellt sich nicht einmal die Frage nach 1NF.

Ich habe gehört, dass argumentiert wurde, dass nullfähige Spalten im Allgemeinen den ersten Grad der Normalisierung durchbrechen.

Siehe oben für den stichhaltigen Grund, der diesem Argument zugrunde liegt.

Aber in der Praxis ist es sehr praktisch.

Nur wenn Sie immun gegen die Kopfschmerzen sind, die normalerweise im Rest der Welt auftreten. Ein solcher Kopfschmerz (und er ist im Vergleich zu anderen nullPhänomenen nur geringfügig ) ist die Tatsache, dass WHERE x=yin SQL tatsächlich bedeutet WHERE x is not null and y is not null and x=y, aber dass die meisten Programmierer sich dieser Tatsache einfach nicht bewusst sind und sie einfach durchlesen. Mal ohne Schaden, mal nicht.

In der Tat verletzen nullfähige Spalten eine der grundlegendsten Regeln für das Datenbankdesign: Kombinieren Sie keine unterschiedlichen Informationselemente in einer Spalte. Nullen tun genau das, weil sie den booleschen Wert "Dieses Feld ist / ist nicht wirklich vorhanden" mit dem tatsächlichen Wert kombinieren.


16
+1 für "WO x nicht null ist und y nicht null ist und x = y". War mir dessen nicht bewusst.
RobM

1
Sehr schön gestaltete Argumente und Beispiele.
Pedz

1
Ein Problem. Wenn der Wert "nicht vorhanden" ist (was ein reales Szenario ist) und das Datenbankattribut keine Nullen zulässt, ist der Wert im Attribut FALSCH. Denken Sie an die Kopfschmerzen, KISS, es bedeutet nicht nur, es einfach zu halten, es bedeutet, es so einfach wie möglich zu halten, aber nicht einfacher. Wenn das "relationale Modell" ein unrealistisches, dummes Ergebnis erfordert, müssen die Regeln möglicherweise erweitert werden, um die erforderlichen realen Daten zu verarbeiten?
Charles Bretana

1
Es hat sich gezeigt, dass eine dreiwertige Logik zu einem Bedarf an vierwertiger Logik führt und dass ein Bedarf an fünfwertiger Logik usw. usw. besteht. Zweiwertige Logik ist ausreichend, aber die Datenstrukturen, die wir erhalten, wenn Wenn man es anwendet, ist "so einfach wie möglich" immer noch weit weniger einfach als "so einfach wie wir wollen".
Erwin Smout

2
Chris Date, Logic & Databases, Kapitel 6, "Warum relationale DBMS-Logik nicht vielwertig sein darf", S. 145. Die Liste der Verweise auf dieses Kapitel sollte ebenfalls interessant sein, insbesondere diejenigen, an denen McGoveran beteiligt ist.
Erwin Smout

13

Ich kann nichts Falsches daran sehen, dass es sich nur um eine optionale n-1-Beziehung handelt, die im Fremdschlüssel mit einer Null dargestellt wird. Andernfalls müssen Sie beim Einfügen Ihrer Link-Tabelle sicherstellen, dass keine nn-Beziehung entsteht, was zu noch mehr Problemen führt.


2
Eigentlich ist es eine 0-N-Beziehung, keine optionale 1-N-Beziehung. Aber ich stimme dir zu.
Eric J.

5
Verwalten? Es ist eine einfache EINZIGARTIGE Einschränkung auf der 0-zu-1-Seite!
wqw

2
Ja, es ist eine EINZIGARTIGE Einschränkung, aber Sie müssen sich auch später mit möglichen Ausnahmen in Ihrem Code befassen, die auf diese Einschränkung zurückzuführen sind ...
pedromarce

4

Optionale Beziehungen sind im relationalen Modell definitiv möglich.

Sie können Nullen verwenden, um das Fehlen einer Beziehung auszudrücken. Sie sind praktisch, verursachen aber dieselben Kopfschmerzen wie Nullen an anderer Stelle. Ein Ort, an dem sie keine Probleme verursachen, sind Joins. Zeilen mit einer Null im Fremdschlüssel stimmen nicht mit Zeilen in der referenzierten Tabelle überein. Also fallen sie aus einer inneren Verbindung heraus. Wenn Sie äußere Verknüpfungen durchführen, werden Sie sowieso mit Nullen zu tun haben.

Wenn Sie Nullen wirklich vermeiden möchten (6. Normalform), können Sie die Tabelle zerlegen. Eine der beiden zerlegten Tabellen enthält zwei Fremdschlüsselspalten. Einer ist der optionale Fremdschlüssel, den Sie haben, und der andere ist ein Fremdschlüssel, der auf den Primärschlüssel der ursprünglichen Tabelle verweist. Jetzt müssen Sie Einschränkungen verwenden, um zu verhindern, dass die Beziehung zu vielen wird. Sie möchten dies verhindern.


2

Die Verwendung von NULL wäre ein guter Weg, um unvollständige Bestellungen zu bereinigen:

SELECT * FROM `orders`
WHERE `started_time` < (UNIX_TIMESTAMP() + 900) AND `customer_id` IS NULL

Die obigen Angaben zeigen Bestellungen, die älter als 15 Minuten sind, ohne eine entsprechende Kunden-ID.


0

Nullable FKs für optionale Viele-zu-Eins-Beziehungen sind völlig in Ordnung.


0

Wenn Sie die Bestellung nur vorübergehend ohne Kunden-ID hinzufügen, bis ein Kunde definiert ist, ist es nicht einfacher, den Kunden und die Bestellung in einer einzigen Transaktion hinzuzufügen, wodurch die Notwendigkeit der Eingabe eines NULL-Fremdschlüssels entfällt und Einschränkungen oder Auslöser vermieden werden Sie haben sich eingerichtet, verletzt zu werden?

Normalerweise tritt diese Situation in Web-Apps auf, in denen die Bestellung detailliert ist, bevor der Kunde definiert, wer er ist. In diesen Situationen wird die Bestellung im Serverstatus oder in einem Cookie gehalten, bis der gesamte für eine vollständige Bestellung erforderliche Status bereitgestellt wurde. Zu diesem Zeitpunkt bleibt die Bestellung in der Datenbank erhalten.

NULL-Fremdschlüssel sind für Dinge wie Adressen in Ordnung, wie oben erwähnt. Ein NULL-Kundenfeld ist jedoch für eine Bestellung nicht sinnvoll und sollte eingeschränkt werden.


Der Auftragskunde war als Beispiel. In meiner App ähnelt es eher Adressen. Es konnte nicht sofort ein Beispiel gefunden werden, das vollständig korrekt war. Vielen Dank.
Lieven Cardoen

1
Dies kann ein gültiges Szenario sein, wenn die Datenbank zum Speichern von Artikeln in einem Warenkorb verwendet wurde, in dem der Warenkorb keinem registrierten Benutzer gehört.
Johnie Karr

0

Sie können Ihrer Kundentabelle jederzeit eine künstliche Zeile hinzufügen, z. B. Id = -1 und CustomerName = 'Unbekannt'. In Fällen, in denen Sie Ihre CustomerId normalerweise in der Reihenfolge NULL festlegen, setzen Sie sie auf -1.

Dies ermöglicht es Ihnen, keine nullbaren FKs zu haben, aber dennoch den Mangel an Daten angemessen darzustellen (und Sie vor nachgeschalteten Benutzern zu bewahren, die nicht wissen, wie sie mit NULL-Werten umgehen sollen).


Denken Sie nur daran, dass NULL-Werte nicht in einem Index (in Oracle) gespeichert werden. Dies bedeutet, dass das Überspringen der Verknüpfungstabelle und die Auswahl der nullbaren FK sinnvoll sind - was die Leistung betrifft. Die andere Sache, von der es abhängen könnte, ist, ob Sie etwas anderes in dieser Link-Tabelle speichern möchten, zum Beispiel, WER hat den Link erstellt und wann? Ist der Link jetzt inaktiv / gelöscht (aber einmal?)
Worthy7

Das ist eine schlechte Idee. Wenn Sie einen Fremdschlüssel festgelegt haben und die Daten, auf die er zeigt, später entfernt werden, wird die Fremdschlüsselausnahme nicht angezeigt, und Ihre Daten sind jetzt sinnlos. Schlimmer noch, wenn diesem Schlüssel später etwas anderes zugewiesen wird, zeigen Sie auf den völlig falschen Kunden
IcedDante

-1

Ich habe gehört, dass argumentiert wurde, dass nullfähige Spalten im Allgemeinen den ersten Normalisierungsgrad durchbrechen. Aber in der Praxis ist es sehr praktisch.


3
Nullable-Spalten können in 1NF bis 5NF sein, aber nicht in 6NF, wie ich gelesen habe.
Walter Mitty

-1

Ja, da stimmt etwas nicht. Es ist kein Fremdschlüssel, wenn es nullbar ist. Sein Datenbankdesign durch Code. Vielleicht machen Sie einen Null-Link zu nicht zugewiesen. oder "Nicht zugewiesen", wenn Sie eine Zeichenspalte verwenden. Bewahren Sie die Integrität Ihrer Daten zu 100%.

Durch die Nutzung unserer Website bestätigen Sie, dass Sie unsere Cookie-Richtlinie und Datenschutzrichtlinie gelesen und verstanden haben.
Licensed under cc by-sa 3.0 with attribution required.