Kann ein Fremdschlüssel NULL und / oder doppelt sein?


325

Bitte klären Sie zwei Dinge für mich:

  1. Kann ein Fremdschlüssel NULL sein?
  2. Kann ein Fremdschlüssel dupliziert werden?

Soweit ich weiß, NULLsollte es nicht in Fremdschlüsseln verwendet werden, aber in einigen meiner Anwendungen kann ich NULLsowohl in Oracle als auch in SQL Server eingeben , und ich weiß nicht warum.


1
@Adrian: Nach meinem besten Wissen kann der Fremdschlüssel nicht null sein, aber er nimmt in SQL Server und Oracle null an. kannst du erklären warum?
Marmeladen

@Jams - lies den Link in meiner Antwort.
JNK

11
Dies kann nicht gelöscht werden, da die Antworten und die Frage nützlich sind. Fühlen Sie sich frei, die Frage zu bearbeiten, um sie zu verbessern.
Jeff Atwood

Bitte teilen Sie die Frage nach Duplikaten ab. Nur der über NULL wird unten beantwortet.
Reinierpost

Antworten:


527

Kurze Antwort: Ja, es kann NULL oder doppelt sein.

Ich möchte erklären, warum ein Fremdschlüssel möglicherweise null oder eindeutig oder nicht eindeutig sein muss. Denken Sie zuerst daran, dass ein Fremdschlüssel lediglich erfordert, dass der Wert in diesem Feld zuerst in einer anderen Tabelle (der übergeordneten Tabelle) vorhanden sein muss. Das ist alles, was ein FK per Definition ist. Null ist per Definition kein Wert. Null bedeutet, dass wir den Wert noch nicht kennen.

Lassen Sie mich Ihnen ein Beispiel aus dem wirklichen Leben geben. Angenommen, Sie haben eine Datenbank, in der Verkaufsvorschläge gespeichert sind. Angenommen, jedem Angebot sind nur ein Verkäufer und ein Kunde zugeordnet. Ihre Angebotstabelle enthält also zwei Fremdschlüssel, einen mit der Kunden-ID und einen mit der Vertriebsmitarbeiter-ID. Zum Zeitpunkt der Erstellung des Datensatzes wird jedoch nicht immer ein Vertriebsmitarbeiter zugewiesen (da noch niemand daran arbeiten kann), sodass die Kunden-ID ausgefüllt wird, die Vertriebsmitarbeiter-ID jedoch möglicherweise null ist. Mit anderen Worten, normalerweise benötigen Sie die Fähigkeit, eine Null-FK zu haben, wenn Sie den Wert zum Zeitpunkt der Dateneingabe möglicherweise nicht kennen, aber andere Werte in der Tabelle kennen, die eingegeben werden müssen. Um Nullen in einer FK zuzulassen, müssen Sie im Allgemeinen nur Nullen in dem Feld zulassen, in dem sich die FK befindet. Der Nullwert unterscheidet sich von der Vorstellung, dass es sich um einen FK handelt.

Ob es eindeutig ist oder nicht, hängt davon ab, ob die Tabelle eine Eins-Eins- oder eine Eins-Viele-Beziehung zur übergeordneten Tabelle hat. Wenn Sie nun eine Eins-zu-Eins-Beziehung haben, ist es möglich, dass Sie alle Daten in einer Tabelle haben, aber wenn die Tabelle zu breit wird oder wenn sich die Daten auf ein anderes Thema beziehen (das Beispiel für Mitarbeiter - Versicherung @tbone) zum Beispiel), dann möchten Sie separate Tabellen mit einem FK. Sie möchten diese FK dann entweder auch zur PK (die die Eindeutigkeit garantiert) oder zu einer eindeutigen Einschränkung machen.

Die meisten FKs sind für eine Eins-zu-Viele-Beziehung und das ist es, was Sie von einem FK erhalten, ohne eine weitere Einschränkung für das Feld hinzuzufügen. Sie haben also beispielsweise eine Auftragstabelle und die Bestelldetailtabelle. Wenn der Kunde zehn Artikel gleichzeitig bestellt, verfügt er über einen Bestell- und zehn Bestelldetailsätze, die dieselbe Bestell-ID wie der FK enthalten.


13
Das soll also besser sein, als einen falschen Verkäufer namens "Unassigned" zu haben?
Thomas Weller

8
Ein Kommentar. Nullen lassen viel Raum für Fehler in der Abfrage von Leuten, die nicht wissen, wie SQL (falsch) mit 3VL umgeht. Wenn ein Verkäufer für eine bestimmte R-Tabelle wirklich nicht erforderlich ist, fügen Sie diesen Datensatz nur nicht hinzu. Eine separate Tabelle kann "ProposalAssignedTo" oder eine solche sein, mit entsprechenden Einschränkungen. Ein Abfrageschreiber kann sich dann dieser Tabelle anschließen und seine eigene Logik für alles bereitstellen, was wir tun möchten, wenn ein Angebot keinen Verkäufer hat. NULL bedeutet nicht nur "wir wissen es nicht" - es kann für viele Dinge verwendet werden (weshalb es fast immer eine schlechte Idee ist)
N West

26
@nWest, ich erlaube nicht inkompetenten Personen, meine Datenbanken abzufragen, und Entwickler, die nicht wissen, wie sie mit Nullen umgehen sollen, sind inkompetent. Es gibt Zeiten, in denen die Daten zum Zeitpunkt der ersten Dateneingabe für ein bestimmtes Feld nicht bekannt sind, die anderen Felder jedoch zu diesem Zeitpunkt benötigt werden.
HLGEM

28
@ThomasWeller Die Referenzierung eines gefälschten Verkäufers ("Nicht zugewiesen") verschlimmert das Problem. Ich gehe davon aus, dass Ihre Verkäufertabelle mehrere Spalten enthält ...? Welche Sozialversicherungsnummer hat Mr. Unassigned? Welcher Abteilung ist er zugeordnet? Wer ist sein Chef? Ich hoffe, Sie verstehen meinen Punkt: Wenn Sie einen "nicht zugewiesenen" Verkäufer erstellen, stellen Sie schnell fest, dass Sie NULLin einer Tabelle gegen mehrere NULLs in einer anderen Tabelle getauscht haben .
Gili

1
@ThomasWeller Sie haben auch ein Problem, wenn Sie Ihre Schnittstelle lokalisieren müssen.
Tobiv


45

Aus dem Maul des Pferdes:

Fremdschlüssel ermöglichen Schlüsselwerte, die alle NULL sind, auch wenn keine übereinstimmenden PRIMARY- oder UNIQUE-Schlüssel vorhanden sind

Keine Einschränkungen für den Fremdschlüssel

Wenn für den Fremdschlüssel keine anderen Einschränkungen definiert sind, kann eine beliebige Anzahl von Zeilen in der untergeordneten Tabelle auf denselben übergeordneten Schlüsselwert verweisen. Dieses Modell erlaubt Nullen im Fremdschlüssel. ...

NOT NULL Einschränkung des Fremdschlüssels

Wenn in einem Fremdschlüssel keine Nullen zulässig sind, muss jede Zeile in der untergeordneten Tabelle explizit auf einen Wert im übergeordneten Schlüssel verweisen, da im Fremdschlüssel keine Nullen zulässig sind.

Eine beliebige Anzahl von Zeilen in der untergeordneten Tabelle kann auf denselben übergeordneten Schlüsselwert verweisen. Daher stellt dieses Modell eine Eins-zu-Viele-Beziehung zwischen dem übergeordneten und dem Fremdschlüssel her. Jede Zeile in der untergeordneten Tabelle muss jedoch einen Verweis auf einen übergeordneten Schlüsselwert enthalten. Das Fehlen eines Wertes (einer Null) im Fremdschlüssel ist nicht zulässig. Das gleiche Beispiel im vorherigen Abschnitt kann verwendet werden, um eine solche Beziehung zu veranschaulichen. In diesem Fall müssen die Mitarbeiter jedoch einen Verweis auf eine bestimmte Abteilung haben.

EINZIGARTIGE Einschränkung für den Fremdschlüssel

Wenn für den Fremdschlüssel eine EINZIGARTIGE Einschränkung definiert ist, kann nur eine Zeile in der untergeordneten Tabelle auf einen bestimmten übergeordneten Schlüsselwert verweisen. Dieses Modell erlaubt Nullen im Fremdschlüssel.

Dieses Modell stellt eine Eins-zu-Eins-Beziehung zwischen dem übergeordneten Schlüssel und dem Fremdschlüssel her, die unbestimmte Werte (Nullen) im Fremdschlüssel zulässt. Angenommen, die Mitarbeitertabelle enthält eine Spalte mit dem Namen MEMBERNO, die sich auf eine Mitarbeitermitgliedsnummer im Unternehmensversicherungsplan bezieht. Außerdem hat eine Tabelle mit dem Namen INSURANCE einen Primärschlüssel mit dem Namen MEMBERNO, und in anderen Spalten der Tabelle sind die entsprechenden Informationen zu einer Mitarbeiterversicherung enthalten. Das MITGLIED in der Mitarbeitertabelle muss sowohl ein Fremdschlüssel als auch ein eindeutiger Schlüssel sein:

  • Durchsetzen von referenziellen Integritätsregeln zwischen den Tabellen EMP_TAB und INSURANCE (die Einschränkung FOREIGN KEY)

  • Um sicherzustellen, dass jeder Mitarbeiter eine eindeutige Mitgliedsnummer hat (die EINZIGARTIGE Schlüsselbeschränkung)

EINZIGARTIGE und NICHT NULL-Einschränkungen für den Fremdschlüssel

Wenn für den Fremdschlüssel sowohl UNIQUE- als auch NOT NULL-Einschränkungen definiert sind, kann nur eine Zeile in der untergeordneten Tabelle auf einen bestimmten übergeordneten Schlüsselwert verweisen. Da im Fremdschlüssel keine NULL-Werte zulässig sind, muss jede Zeile in der untergeordneten Tabelle explizit verweisen ein Wert im übergeordneten Schlüssel.

Sieh dir das an:

Oracle 11g Link


16

Ja, Fremdschlüssel können null sein, wie oben von erfahrenen Programmierern angegeben. Ich würde ein weiteres Szenario hinzufügen, in dem Fremdschlüssel null sein müssen. Angenommen, wir haben Tabellenkommentare, Bilder und Videos in einer Anwendung, die Kommentare zu Bildern und Bildern zulässt Videos. In der Kommentartabelle können wir zwei Fremdschlüssel-Bild-ID und Videos-ID zusammen mit der Primärschlüssel-Kommentar-ID haben. Wenn Sie also nur ein Video kommentieren, ist nur die VideosId erforderlich und die Bild-ID wäre null ... und wenn Sie ein Bild kommentieren, ist nur die Bild-ID erforderlich und die Videos-ID wäre null ...


1
Ich denke, es gibt einen besseren Weg, um dieses Problem zu lösen. Anstatt neue Spalten zu erstellen, können Sie zwei Spalten verwenden, nämlich "id" und "type", die die ID und den Namen der Fremdschlüsseltabelle enthalten. Beispiel: id = 1, type = Picture stellt einen Link zur Picture-Tabelle mit id 1 dar. Der Vorteil dieser Lösung besteht darin, dass Sie keine neuen Spalten erstellen müssen, wenn Kommentare zu zusätzlichen Tabellen hinzugefügt werden. Nachteil ist keine Fremdschlüsseleinschränkung auf DB-Ebene, sondern die Einschränkung muss App-Ebene sein.
Agent47DarkSoul

4
@Agent: Wir hatten diese "Lösung" in der Produktion. Tu es nicht, es ist schrecklich. Das Erstellen von Abfragen wird zu einem Durcheinander von "Wenn es Typ 1 ist, verbinden Sie sich mit dieser Tabelle, andernfalls verbinden Sie sich mit dieser". Es war ein Albtraum für uns. Am Ende haben wir das getan, was in dieser Antwort steht, und für jeden Join-Typ eine neue Spalte erstellt. Das Erstellen von Spalten ist billig. Es ist so ziemlich der einzige Fehler, dass viele Spalten die Verwendung von Toad erschweren, aber das ist nur ein Fehler von Toad.
user128216

1
@FighterJet Rails bietet ein großartiges ORM-Framework, das mit dieser Lösung auch komplexe Abfragen bearbeitet.
Agent47DarkSoul

2
@Agent: Vielleicht kann es ... aber wenn Sie es einfach machen können, warum es komplex machen? Und vielleicht war "Albtraum" das falsche Wort: Es war einfach sehr unpraktisch. Wir hatten (viel) keine Probleme mit der Datenintegrität.
user128216

7

Es hängt davon ab, welche Rolle dies foreign keyin Ihrer Beziehung spielt.

  1. Wenn dies foreign keyauch key attributein Ihrer Beziehung ist, kann es nicht NULL sein
  2. Wenn dies foreign keyein normales Attribut in Ihrer Beziehung ist, kann es NULL sein.

3

Hier ist ein Beispiel mit der Oracle-Syntax:
Zuerst erstellen wir eine Tabelle COUNTRY

CREATE TABLE TBL_COUNTRY ( COUNTRY_ID VARCHAR2 (50) NOT NULL ) ;
ALTER TABLE TBL_COUNTRY ADD CONSTRAINT COUNTRY_PK PRIMARY KEY ( COUNTRY_ID ) ;

Erstellen Sie die Tabelle PROVINZ

CREATE TABLE TBL_PROVINCE(
PROVINCE_ID VARCHAR2 (50) NOT NULL ,
COUNTRY_ID  VARCHAR2 (50)
);
ALTER TABLE TBL_PROVINCE ADD CONSTRAINT PROVINCE_PK PRIMARY KEY ( PROVINCE_ID ) ;
ALTER TABLE TBL_PROVINCE ADD CONSTRAINT PROVINCE_COUNTRY_FK FOREIGN KEY ( COUNTRY_ID ) REFERENCES TBL_COUNTRY ( COUNTRY_ID ) ;

Dies läuft in Oracle einwandfrei. Beachten Sie, dass der Fremdschlüssel COUNTRY_ID in der zweiten Tabelle nicht "NOT NULL" enthält.

Um nun eine Zeile in die PROVINCE-Tabelle einzufügen, reicht es aus, nur die PROVINCE_ID anzugeben. Wenn Sie jedoch auch eine COUNTRY_ID angeben möchten, muss diese bereits in der COUNTRY-Tabelle vorhanden sein.


1

Standardmäßig gibt es keine Einschränkungen für den Fremdschlüssel. Der Fremdschlüssel kann null und doppelt sein.

Wenn Sie beim Erstellen einer Tabelle / Ändern der Tabelle eine Einschränkung der Eindeutigkeit hinzufügen oder nicht null, werden nur die Werte null / duplizieren nicht zugelassen.


0

Einfach ausgedrückt, "Nicht identifizierende" Beziehungen zwischen Entitäten sind Teil des ER-Modells und stehen in Microsoft Visio beim Entwerfen des ER-Diagramms zur Verfügung. Dies ist erforderlich, um die Kardinalität zwischen Entitäten vom Typ "Null oder mehr als Null" oder "Null oder Eins" zu erzwingen. Beachten Sie diese "Null" in der Kardinalität anstelle von "Eins" in "Eins zu Viele".

Ein Beispiel für eine nicht identifizierende Beziehung, bei der die Kardinalität "Null" sein kann (nicht identifizierend), ist, wenn wir sagen, dass ein Datensatz / Objekt in einer Entität - A "möglicherweise" oder "möglicherweise nicht" einen Wert als Referenz auf den Datensatz hat / s in einer anderen Entität-B.

Da es eine Möglichkeit gibt, dass sich ein Datensatz von Entität A gegenüber den Datensätzen anderer Entität B identifiziert, sollte in Entität B eine Spalte vorhanden sein, in der der Identitätswert des Datensatzes von Entität B angegeben ist. Diese Spalte kann "Null" sein, wenn kein Datensatz in Entität A den Datensatz (oder die Objekte) in Entität B identifiziert.

Im objektorientierten (realen) Paradigma gibt es Situationen, in denen ein Objekt der Klasse B für seine Existenz nicht unbedingt vom Objekt der Klasse A abhängt (stark gekoppelt ist), was bedeutet, dass die Klasse B lose mit der Klasse A gekoppelt ist Eine solche, dass Klasse-A ein Objekt der Klasse-A "enthalten" (enthalten) kann, im Gegensatz zum Konzept des Objekts der Klasse-B, muss (Zusammensetzung) ein Objekt der Klasse-A haben, für sein (Objekt der Klasse-) B) Schöpfung.

Aus Sicht der SQL-Abfrage können Sie alle Datensätze in Entität B abfragen, die für den für Entität B reservierten Fremdschlüssel "nicht null" sind. Dadurch werden alle Datensätze mit einem bestimmten entsprechenden Wert für Zeilen in Entität-A angezeigt. Alternativ sind alle Datensätze mit dem Wert Null die Datensätze, die in Entität-A in Entität-B keinen Datensatz haben.


-1

Ich denke, es ist besser, die mögliche Kardinalität zu berücksichtigen, die wir in den Tabellen haben. Wir können eine mögliche minimale Kardinalität von Null haben. Wenn dies optional ist, kann die Mindestbeteiligung von Tupeln aus der zugehörigen Tabelle Null sein. Jetzt müssen Fremdschlüsselwerte auf Null gesetzt werden.

Aber die Antwort ist, dass alles vom Geschäft abhängt.


-3

Die Idee eines Fremdschlüssels basiert auf dem Konzept, auf einen Wert zu verweisen, der bereits in der Haupttabelle vorhanden ist. Aus diesem Grund wird es in der anderen Tabelle als Fremdschlüssel bezeichnet. Dieses Konzept wird als referenzielle Integrität bezeichnet. Wenn ein Fremdschlüssel als Nullfeld deklariert wird, verstößt er gegen die Logik der referenziellen Integrität. Worauf wird es sich beziehen? Es kann sich nur auf etwas beziehen, das in der Haupttabelle vorhanden ist. Daher halte ich es für falsch, ein Fremdschlüsselfeld als null zu deklarieren.


Es kann auf "nichts" verweisen oder Sie kennen seinen Wert noch nicht NULL, aber die referenzielle Integrität besagt, dass es dort sein muss, wenn es auf "etwas" verweist.
Yaxe

-7

Ich denke, der Fremdschlüssel einer Tabelle ist auch der Primärschlüssel einer anderen Tabelle. Es werden also keine Nullen zugelassen. Es gibt also keine Frage, ob der Fremdschlüssel einen Nullwert enthält.

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.