Ist es in Ordnung, einen Fremdschlüssel als Primärschlüssel zu haben?


102

Ich habe zwei Tabellen:

  • Benutzer (Benutzername, Passwort)
  • Profil (Profil-ID, Geschlecht, Geburtsdatum, ...)

Derzeit verwende ich diesen Ansatz: Jeder Profildatensatz hat ein Feld mit dem Namen "userId" als Fremdschlüssel, das mit der Benutzertabelle verknüpft ist. Wenn sich ein Benutzer registriert, wird sein Profildatensatz automatisch erstellt.

Ich bin verwirrt mit dem Vorschlag meines Freundes: das Feld "userId" als Fremd- und Primärschlüssel zu verwenden und das Feld "profileId" zu löschen. Welcher Ansatz ist besser?


3
Entity Framework generiert dies (mit Code zuerst) für zeroOrOne (und one)-to-one-Beziehungen. Also ... es ist möglich. Ist es der beste Weg ... Das ist eine andere Frage. Aber es ist gültig. Ich habe das nie gemacht, als ich meine eigenen Datenbanken erstellt habe (aber ich habe sogar nie daran gedacht).
Raphaël Althaus

Antworten:


132

Fremdschlüssel sind fast immer "Duplikate zulassen", was sie als Primärschlüssel ungeeignet macht.

Suchen Sie stattdessen ein Feld, das jeden Datensatz in der Tabelle eindeutig identifiziert, oder fügen Sie ein neues Feld (entweder eine automatisch inkrementierende Ganzzahl oder eine GUID) als Primärschlüssel hinzu.

Die einzige Ausnahme bilden Tabellen mit einer Eins-zu-Eins- Beziehung, bei der der Fremdschlüssel und der Primärschlüssel der verknüpften Tabelle identisch sind.


73
Ein zusammengesetzter Primärschlüssel, der aus zwei Fremdschlüsseln besteht, eignet sich auch hervorragend zum Implementieren von Viele-zu-Viele-Beziehungen.
Rechtsfalte

1
@rezadru: Es liegt mir fern, mit Rightfold nicht einverstanden zu sein, aber ein Ersatzschlüssel ist fast immer die bessere Wahl.
Robert Harvey

4
Nichts an einem Fremdschlüssel schreibt vor, dass es sich um eine 1 zu viele handelt (oder "Duplikate zulassen", wie geschrieben). Wichtige Einschränkungen und Eindeutigkeit sind zwei separate Konzepte in einer Datenbank und können genauso einfach gemischt werden wie das Hinzufügen eines Index (was ein drittes separates Konzept wäre).
Blindguy

40

Primärschlüssel müssen immer eindeutig sein, Fremdschlüssel müssen nicht eindeutige Werte zulassen, wenn die Tabelle eine Eins-zu-Viele-Beziehung ist. Es ist vollkommen in Ordnung, einen Fremdschlüssel als Primärschlüssel zu verwenden, wenn die Tabelle durch eine Eins-zu-Eins-Beziehung verbunden ist, nicht durch eine Eins-zu-Viele-Beziehung. Wenn Sie möchten, dass derselbe Benutzerdatensatz die Möglichkeit hat, mehr als einen zugehörigen Profildatensatz zu haben, verwenden Sie einen separaten Primärschlüssel, andernfalls bleiben Sie bei dem, was Sie haben.


11

Ja, es ist legal, dass ein Primärschlüssel ein Fremdschlüssel ist. Dies ist ein seltenes Konstrukt, aber es gilt für:

  • eine 1: 1 Beziehung. Die beiden Tabellen können nicht in einer zusammengeführt werden, da unterschiedliche Berechtigungen und Berechtigungen nur auf Tabellenebene gelten (ab 2017 wäre eine solche Datenbank ungerade).

  • eine 1: 0..1 Beziehung. Das Profil kann je nach Benutzertyp vorhanden sein oder nicht.

  • Die Leistung ist ein Problem, und das Design fungiert als Partition: Auf die Profiltabelle wird selten zugegriffen, sie wird auf einer separaten Festplatte gehostet oder es gibt eine andere Sharding-Richtlinie als in der Benutzertabelle. Wäre nicht sinnvoll, wenn der unterstrichene Speicher säulenförmig ist.


Es würde eine negative Leistung geben, wenn die Tabellen häufig verbunden würden, was zu der normalen Empfehlung führt, dass 1 Tabelle besser ist. In einigen Fällen wird immer separat auf die Daten zugegriffen, nicht verbunden, und es kann organisatorische Vorteile haben, zwei Tabellen mit einer 1: 1-Beziehung zu haben.
Blindguy

4

Es wird allgemein als schlechte Praxis angesehen, eine Eins-zu-Eins-Beziehung zu haben. Dies liegt daran, dass Sie die Daten einfach in einer Tabelle darstellen und das gleiche Ergebnis erzielen können.

Es gibt jedoch Fälle, in denen Sie diese Änderungen möglicherweise nicht an der Tabelle vornehmen können, auf die Sie verweisen. In diesem Fall ist es kein Problem, den Fremdschlüssel als Primärschlüssel zu verwenden. Es kann hilfreich sein, einen zusammengesetzten Schlüssel zu haben, der aus einem automatisch inkrementierenden eindeutigen Primärschlüssel und dem Fremdschlüssel besteht.

Ich arbeite derzeit an einem System, auf dem sich Benutzer anmelden und einen Registrierungscode für eine App generieren können. Aus Gründen, auf die ich nicht eingehen möchte, kann ich die erforderlichen Spalten nicht einfach zur Benutzertabelle hinzufügen. Also gehe ich eine Eins-zu-Eins-Route mit der Codetabelle.


2
Ich stimme Ihnen größtenteils zu, dass es viele Vorteile hat, alle Daten in derselben Tabelle als zusätzliche Spalten zu haben. Obwohl dies geschrieben wurde .. "Sie könnten nur die Daten in einer Tabelle darstellen lassen und das gleiche Ergebnis erzielen" ..: Eine separate Tabelle kann nützlich sein, zum Beispiel hier, wenn der Eintrag in der Profiltabelle optional ist. Beispielsweise verfügt möglicherweise nicht jeder Bankkunde über eine Internetbanking-Registrierung. In diesem Fall könnte die IB-Registrierungstabelle verwendet werden, um zu verhindern, dass andere Tabellen weitere untergeordnete Datensätze haben. Auch hier könnte dies mit einer neuen PK für die IB-Registrierungstabelle geschehen.
Teddy

1
@ Teddy Ebenso stimme ich größtenteils dem zu, was du gesagt hast. In der ursprünglichen Frage heißt es jedoch "... sein Profildatensatz wird automatisch erstellt ...", was bedeutet, dass die Profiltabelle nicht optional ist. In einer Situation, in der die Profiltabelle optional war, ist es ja möglich, sie als separate Tabelle zu haben. Andererseits könnten sie einfach nullfähige Spalten in derselben Tabelle verwenden.
Tshsmith

1
Mit einer separaten zweiten Tabelle können wir den Eintrag in eine dritte Tabelle verhindern, die nur für Personen zulässig ist, die einen Eintrag in der zweiten Tabelle haben.
Teddy

Absolut, aber wenn wir die 1-zu-1-Tabellen zusammenführen, können wir verhindern, dass Personen mit Nullwerten auf die dritte (technisch zweite) Tabelle zugreifen. Die Frage, die OP gestellt hat, enthält jedoch die Zeile "... bei der Anmeldung ... ... wird sein Profildatensatz automatisch erstellt ...", wodurch dies überflüssig wird.
Tshsmith

Mein Hauptgrund dafür ist, dass es beim Data Warehousing eine gute Praxis ist, Fakten- und Dimensionstabellen zu trennen. Die separaten Fakten- und Dimensionstabellen sind nützliche Hinweise für die Arbeit mit Software wie PowerPivot, PowerBI und Tableau.
Marco Rosas

4

Ja, ein Fremdschlüssel kann bei einer Eins-zu-Eins-Beziehung zwischen diesen Tabellen ein Primärschlüssel sein


2
Dies ist auch nützlich für das Design von Supertyp-Subtyp. Der Primärschlüssel für Subtyp-Tabellen sollte eine Fremdschlüsselreferenz auf die Supertyp-Tabelle sein.
Axelioo

2

Ich würde das nicht tun. Ich würde den profileIDals Primärschlüssel der Tabelle behaltenProfile

Ein Fremdschlüssel ist nur eine referenzielle Einschränkung zwischen zwei Tabellen

Man könnte argumentieren, dass ein Primärschlüssel als Ziel aller Fremdschlüssel erforderlich ist, die aus anderen Tabellen darauf verweisen. Ein Fremdschlüssel ist eine Menge von einer oder mehreren Spalten in einer Tabelle (nicht unbedingt ein Kandidatenschlüssel, geschweige denn der Primärschlüssel dieser Tabelle), die die Werte enthalten können, die in den Primärschlüsselspalten einiger gefunden werden andere Tabelle. Wir müssen also einen Primärschlüssel haben, der mit dem Fremdschlüssel übereinstimmt. Oder müssen wir? Der einzige Zweck des Primärschlüssels im Primärschlüssel / Fremdschlüssel-Paar besteht darin, eine eindeutige Verknüpfung bereitzustellen, um die referenzielle Integrität in Bezug auf die "Fremd" -Tabelle aufrechtzuerhalten, die den referenzierten Primärschlüssel enthält. Dies stellt sicher, dass der Wert, auf den sich der Fremdschlüssel bezieht, immer gültig ist (oder null, falls zulässig).

http://www.aisintl.com/case/primary_and_foreign_key.html


1
Möglicherweise - wenn Sie die FK-Einschränkung zwischen User.UserID und Profile.UserID haben, wird dringend empfohlen, einen Index für Profile.UserID zu haben. Warum nicht den primären Clustered-Index für das Tabellenprofil festlegen, wodurch ein zweiter Index und eine Menge unnötiger Arbeit für das Datenbankmodul gespeichert werden?
Umgekehrter Ingenieur

1

Das hängt vom Geschäft und vom System ab.

Wenn Ihre Benutzer-ID eindeutig ist und jederzeit eindeutig ist, können Sie die Benutzer-ID als Primärschlüssel verwenden. Aber wenn Sie jemals Ihr System erweitern möchten, wird es die Dinge schwierig machen. Ich empfehle Ihnen, dem Tabellenbenutzer einen Fremdschlüssel hinzuzufügen, um eine Beziehung zum Tabellenprofil herzustellen, anstatt einen Fremdschlüssel zum Tabellenprofil hinzuzufügen.


0

Kurze Antwort: ABHÄNGIG .... In diesem speziellen Fall könnte es in Ordnung sein. Experten werden jedoch fast jedes Mal davon abraten; einschließlich Ihres Falles.

Warum?

Schlüssel sind in Tabellen selten eindeutig, wenn sie der betreffenden Tabelle fremd sind (aus einer anderen Tabelle stammen). Beispielsweise kann eine Artikel-ID in einer ITEMS-Tabelle eindeutig sein, jedoch nicht in einer ORDERS-Tabelle, da derselbe Artikeltyp höchstwahrscheinlich in einer anderen Reihenfolge vorhanden ist. Ebenso können Auftrags-IDs in der Tabelle ORDERS eindeutig sein (möglicherweise), jedoch nicht in einer anderen Tabelle wie ORDER_DETAILS, in der eine Bestellung mit mehreren Werbebuchungen vorhanden sein kann. Um eine bestimmte Position in einer bestimmten Reihenfolge abzufragen, müssen zwei verknüpft werden FK (order_id und item_id) als PK für diese Tabelle.

Ich bin kein DB-Experte, aber wenn Sie logisch rechtfertigen können, einen automatisch generierten Wert als PK zu haben, würde ich das tun. Wenn dies nicht praktikabel ist, kann eine Verkettung von zwei (oder mehr) FK als PK dienen. ABER ich kann mir keinen Fall vorstellen, in dem ein einzelner FK-Wert als PK gerechtfertigt werden kann.

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.