Angenommen, ich habe das folgende ER-Diagramm:
Wenn ich nun die Beziehung mit einem Fremdschlüssel von School
in darstelle Student
, könnte ich NULL
Werte haben (da a Student
nicht zu a gehören muss School
), zum Beispiel:
Der richtige Weg (basierend auf dem, was ich gelesen habe) ist es, eine Schnittpunkttabelle zu erstellen, um die Beziehung darzustellen, zum Beispiel:
Auf diese Weise können keine NULL
Werte in der Tabelle vorhanden sein School_has_Student
.
Was sind die Nachteile der Verwendung eines nullbaren Fremdschlüssels anstelle der Erstellung einer Schnittstellentabelle?
Bearbeiten:
Ich habe fälschlicherweise ( school_id
, student_id
) als Primärschlüssel für die School_has_Student
Tabelle gewählt, wodurch die Beziehung viele-zu-viele wurde. Der richtige Primärschlüssel sollte gewesen sein student_id
:
Antworten:
Die beiden Modelle repräsentieren unterschiedliche Beziehungen.
Mithilfe einer Verknüpfungstabelle modellieren Sie eine Viele-zu-Viele-Beziehung.
Mit einem einfachen Fremdschlüssel modellieren Sie eine Eins-zu-Viele-Beziehung.
Der Nachteil eines nullbaren Fremdschlüssels besteht darin, dass die Beziehung nicht als Viele-zu-Viele-Beziehung modelliert werden kann, wenn Sie dies versuchen.
Basierend auf Ihrer Bearbeitung der Frage teilen Sie die Schülertabelle effektiv in zwei Tabellen mit demselben Schlüssel auf. Ich sehe dies im Allgemeinen auf Tabellen, die viel zu viele Felder haben, so dass jemand sie in zwei Teile aufteilt, um sie besser handhaben zu können (ich nenne es ein Schwein, das Lippenstift auflegt).
Durch Aufteilen der Schülertabelle machen Sie die zweite Tabelle optional, da in der zweiten Tabelle kein Datensatz vorhanden sein muss. Das ist einem Feld sehr ähnlich, das nicht gesetzt werden muss, weil es null sein kann.
Wenn Sie eine Eins-zu-Viele-Beziehung wünschen, ist es weitaus besser, eine einzelne Tabelle zu verwenden und zuzulassen, dass die Schul-ID in der Schülertabelle null ist. Es gibt keinen Grund, Nullen in Feldern zu vermeiden, selbst für einen Fremdschlüssel. Das bedeutet, dass die Fremdbeziehung optional ist: Entwickler und Datenbankadministratoren wissen das genau, und das zugrunde liegende Datenbankmodul sollte auf jeden Fall einwandfrei funktionieren.
Machen Sie sich keine Sorgen, wenn Sie über Joins besorgt sind. Es gibt genau definierte Semantiken für die Arbeitsweise von Joins mit Nullfeldern. Wenn Sie eine einzelne Tabelle verwenden, können Sie zwei Tabellen anstelle von drei verknüpfen.
quelle
NULL
Werte haben kann ?student_id
einen Primärschlüssel in derSchool_has_Student
Tabelle erstellt, wodurch die Beziehung eins zu viele blieb. Welche Nachteile hat diese Methode gegenüber der Verwendung eines Fremdschlüssels?Sie haben oben in einem Kommentar geschrieben:
Wenn die Fremdschlüsselspalte viele NULL-Werte enthält, müssen Ihre Programme diese meist leere Spalte für jeden Datensatz, den sie verarbeiten, verarbeiten. Die Spalte wird wahrscheinlich etwas Speicherplatz belegen, obwohl sie in 98% aller Fälle leer ist. Das Abfragen der Beziehung bedeutet, dass die Spalte abgefragt wird, die Ihnen mehr Netzwerkverkehr bietet, und wenn Sie einen ORM verwenden, der Ihre Klassen aus Ihren Tabellen und Programmen generiert wird auch mehr Platz auf der Client-Seite benötigen als nötig. Durch die Verwendung einer Schnittstellentabelle wird dies vermieden. Es sind nur Verknüpfungsdatensätze erforderlich, bei denen der entsprechende Fremdschlüssel andernfalls nicht NULL wäre.
Wenn Sie dagegen nicht nur wenige NULL-Werte haben, sagen wir, dass 50% oder mehr Relationen nicht NULL sind. Wenn Sie eine Schnittstellentabelle verwenden, erhalten Sie den gegenteiligen Effekt - mehr Speicherplatz, höhere Komplexität, was zu mehr Netzwerkverkehr usw. führt.
Die Verwendung einer Schnittstellentabelle ist also nur eine Form der Optimierung, die nur für einen bestimmten Fall sinnvoll ist, und insbesondere heutzutage, wo Speicherplatz und Arbeitsspeicher billiger wurden, viel seltener benötigt wird. Beachten Sie, dass "Fundamentals of Database Systems" ursprünglich vor mehr als 20 Jahren geschrieben wurde (ich habe einen Verweis auf die zweite Ausgabe von 1994 gefunden), und ich vermute, dass die Empfehlung zu diesem Zeitpunkt bereits da war. Vor 1994 war die Speicherplatzoptimierung wahrscheinlich viel wichtiger als heute, da Massenspeicher noch teurer und Computer und Netzwerke viel langsamer waren als heute.
Als Randnotiz zu einem wählerischen Kommentar: Die obige Aussage versucht nur zu ahnen, was der Autor von "Fundamentals of Database Systems" mit seiner Empfehlung vor Augen hatte. Ich denke, er machte eine grobe, allgemeine Aussage, die für die meisten Systeme gültig ist. In einigen Datenbanken gibt es andere mögliche Optimierungen wie "Spalten mit geringer Dichte", die die Verwendung einer Schnittstellentabelle noch überflüssiger machen.
Verstehen Sie diese Empfehlung also nicht falsch. Das Buch sagt Ihnen nicht, dass Sie Kreuzungstabellen für
{0,1}:n
Beziehungen im Allgemeinen bevorzugen sollen oder - wie Sie geschrieben haben - dass dies der "richtige Weg" ist. Verwenden Sie Optimierungen wie diese, die Ihre Programme nur dann komplizierter machen, wenn Sie sie wirklich benötigen.quelle
Das konzeptionelle Modell wird so aussehen, was umso weniger unorthodox ist :
Das physikalische Modell wird so aussehen, was umso weniger verwirrend ist (die Leute werden denken, dass es M: M ist, wenn sie nicht genau hinsehen):
Mein Vorschlag:
Wenn Sie möchten, trennen viele Spalten (FK oder andere), die für die meisten Schüler nicht zutreffen, die Tabellen in Rollentabellen mit 1: 1 rels. Das liegt aber nicht daran, dass es sich um FK handelt, sondern daran, dass die Spalten nicht für die meisten Zeilen gelten.
Andernfalls sind nullfähige FK ein normaler Teil einer Datenbank und Join-Tabellen sind normalerweise für M: M-Rels.
1: 1-Rels werden häufig für Rollentabellen mit Spalten verwendet, die nur dann gelten, wenn die Entität von einem bestimmten Typ ist, und um BLOB-Spalten aus Leistungs- oder Speichergründen zu extrahieren. Das Vermeiden von Nullwerten in FKs ist dafür keine gebräuchliche Verwendung.
quelle
Neben anderen Antworten möchte ich darauf hinweisen, dass ein Nullwert für den Fremdschlüssel nicht eindeutig ist. Heisst das:
1) Die Schule des Schülers (falls vorhanden) ist unbekannt (dies ist die Standardbedeutung von 'null' - Wert ist unbekannt)
2) Es ist bekannt, ob der Schüler eine Schule hat oder nicht, und sie haben keine
Wenn Sie die Standardbedeutung von null verwenden, wie würden Sie "Schüler hat keine Schule" in Ihrem Fremdschlüsselmodell darstellen? In diesem Fall müssten Sie wahrscheinlich einen Eintrag "Keine Schule" mit einer eigenen ID in der Schultabelle erstellen. (Nicht ideal)
quelle
NULL
, es kann bedeuten: 1) Unbekannter Wert. 2) Nicht verfügbar oder Wert einbehalten. 3) Nicht zutreffendes Attribut (Ich denke, diese Interpretation bedeutet, dass Sie einenNULL
für einen Fremdschlüssel angeben können ).Datenbanktabellen haben diese nette Sache, die Beschränkungen genannt wird. Es ist also sehr einfach, eine Kreuzungstabelle zu erstellen, in der nur 1 Schüler in der Tabelle, aber viele Schulen in der Tabelle angezeigt werden. Effektiv geben Sie ein
Theorie ist nett, aber am Ende werden Sie Ihre Datenbank nach den Fragen modellieren, die Sie stellen.
Wenn Sie häufig mit der Frage fragen möchten: "Welche Schüler sind in meiner Schule?", Möchten Sie wirklich die gesamte Schülertabelle abfragen oder eine einfache Schnittstellentabelle haben.
In Datenbanken: Optimieren Sie für die von Ihnen gestellten Fragen.
quelle
Es gibt einen Anwendungsfall, in dem die Verwendung einer dritten Tabelle tatsächlich sinnvoll sein kann. Das Beispiel mag rein hypothetisch erscheinen, aber ich hoffe, es verdeutlicht meinen Standpunkt gut. Nehmen wir an, Sie fügen der
students
Tabelle weitere Spalten hinzu und beschließen, die Eindeutigkeit der Datensätze über einen zusammengesetzten Index für mehrere Spalten zu erzwingen. Es ist sehr wahrscheinlich, dass Sie auch dieschool_id
Spalte einschließen müssen , und hier beginnen die Dinge chaotisch zu werden. Aufgrund der Art und Weise wurde SQL entworfen, mehrere identische Datensätze eingefügt , woschool_id
istNULL
möglich sein wird. Aus technischer Sicht macht es durchaus Sinn, ist jedoch nicht intuitiv und kann zu unerwarteten Ergebnissen führen. Andererseits ist es einfach, die Eindeutigkeit der Kreuzungstabelle durchzusetzen.Ich musste kürzlich eine solche "optionale" Beziehung modellieren, bei der die Anforderung einer Eindeutigkeitsbeschränkung auf eine Zeitstempelspalte zurückzuführen war. Das Verlassen des nullbaren Fremdschlüssels in der Tabelle führt plötzlich dazu, dass Datensätze mit demselben Zeitstempel eingefügt werden können (nehmen wir an, es handelt sich um einen Standarddatensatz für Datensätze, die noch nicht geprüft / genehmigt wurden). Der einzige Ausweg war das Entfernen nullfähige Spalte.
Wie Sie sehen, handelt es sich also um einen ziemlich speziellen Fall, und wie andere angemerkt haben, sind Sie mit allen
NULL
Werten in den meisten Fällen vollkommen einverstanden . Es hängt wirklich von den spezifischen Anforderungen Ihres Modells ab.quelle
Zusätzlich zu den vielen guten Vorschlägen, die bereits eingereicht wurden, bin ich persönlich kein Fan von Fremdschlüsseln, es sei denn, sie sind wirklich notwendig. Zunächst gibt es die M: M-Beziehung, auf die Sie verweisen. Das Aufrufen eines Fremdschlüssels und damit das Abrufen dieser Tabellendaten in Ihre Abfragen führt zu einer höheren Komplexität und je nach Tabellengröße zu einer langsameren Leistung. Wie bereits erwähnt, können nullfähige FK-Felder nicht unterstützt werden und Probleme mit der Datenintegrität verursachen.
Wenn Sie einen Zustand definieren, in dem die Schule des Schülers unbekannt oder leer ist, werden diese Bedingungen durch NULL nicht unterschieden. (Wieder sind wir zur Datenintegrität zurückgekehrt.) Der Rollentabellenvorschlag von Tulains ist elegant und lässt Nullwerte sauber zu.
quelle