Soll ich Primärschlüssel mit mehreren Spalten verwenden oder eine neue Spalte hinzufügen?

15

In meinem aktuellen Datenbankdesign wird ein Primärschlüssel mit mehreren Spalten verwendet, um vorhandene Daten zu verwenden (die ohnehin eindeutig wären), anstatt eine zusätzliche Spalte zu erstellen, die jedem Eintrag einen beliebigen Schlüssel zuweist. Ich weiß, dass dies zulässig ist, habe mich aber gefragt, ob dies eine Übung ist, die ich vorsichtig anwenden und möglicherweise vermeiden möchte (ähnlich wie bei goto in C).

Was sind also einige der Nachteile, die ich bei diesem Ansatz sehen könnte, oder Gründe, warum ich einen einspaltigen Schlüssel haben möchte?

Covar
quelle
2
Ich weiß nicht, ich denke, das wäre auf SO besser gewesen.
FrustratedWithFormsDesigner
2
@FrustratedWithFormsDesigner Es könnte zu SO kommen, aber ich denke, es funktioniert auch hier, da der Fokus der Frage eher auf den "Vor- und Nachteilen dieses Ansatzes" als auf "Wie mache ich X?" Zu liegen scheint.
Adam Lear
@Anna Lear ♦: Es ist ein "Für und Wider" bei Entwurfsentscheidungen, das sich direkt und eindeutig auf die Codierung auswirkt. Ich denke also, SO wäre ein besserer Ort.
FrustratedWithFormsDesigner

Antworten:

8

Wenn Sie eine Tabelle mit einem mehrspaltigen Primärschlüssel haben, ist dies in der Regel das Ergebnis einer Join-Tabelle (viele zu viele), die zu einer eigenen Entität heraufgestuft wurde (und daher ihren eigenen Primärschlüssel verdient). Es gibt viele, die argumentieren, dass eine Join-Tabelle standardmäßig eine Entität sein sollte, aber das ist eine Diskussion für einen anderen Tag.

Betrachten wir eine hypothetische Beziehung von vielen zu vielen:

Student * --- * Klasse

(Ein Schüler kann in mehreren Klassen sein, eine Klasse kann mehrere Schüler haben).

Zwischen diesen beiden Tabellen befindet sich eine Junction-Tabelle mit dem Namen StudentClass (oder ClassStudent, je nachdem, wie Sie sie schreiben). Manchmal möchten Sie Dinge nachverfolgen, wie wenn der Schüler in der Klasse war. So fügen Sie es der StudentClass-Tabelle hinzu. Zu diesem Zeitpunkt ist StudentClass zu einer einzigartigen Entität geworden ... und sollte einen Namen erhalten, um sie als solche zu erkennen, z. B. Einschreibung.

Schüler 1 --- * Einschreibung * --- 1 Klasse

(Ein Schüler kann viele Einschreibungen haben, jede Einschreibung ist für eine Klasse (oder umgekehrt, eine Klasse kann viele Einschreibungen haben, jede Einschreibung ist für einen Schüler).

Nun können Sie beispielsweise abfragen, wie viele Schüler im vergangenen Jahr in der Klasse Chemie 101 eingeschrieben waren. Oder in welchen Klassen war der Student John Doe während seines Studiums an der Acme University eingeschrieben? Dies war ohne den separaten Primärschlüssel möglich. Wenn Sie jedoch einen Primärschlüssel für die Anmeldung haben, können Sie diese Anmeldungen (nach ID) einfacher abfragen. Wie viele Schüler haben eine bestandene Note erhalten?

Die Entscheidung, ob eine Entität eine PK verdient, hängt davon ab, wie viel Abfragen (oder Manipulationen) Sie für diese Entität ausführen. Nehmen wir zum Beispiel an, Sie wollten die Aufgaben anhängen, die für einen Schüler in einer Klasse erledigt wurden. Der logische Ort zum Anhängen dieser Entität (Zuweisung) befindet sich in der Registrierungsentität. Wenn Sie der Registrierung einen eigenen Primärschlüssel geben, werden die Zuweisungsabfragen einfacher.

Michael Brown
quelle
1
So fügen Sie es der StudentClass-Tabelle hinzu. Zu diesem Zeitpunkt ist StudentClass zu einer einzigartigen Entität geworden ... und sollte einen Namen erhalten, um sie als solche zu erkennen, z. B. Einschreibung. Es ist so einfach, aber es ist so wertvoll, dies zu tun!
Botis
8

Es ist sinnvoll, eine separate ID-Spalte zu haben. Wenn Sie etwas aus Ihrer Datenbanktabelle abrufen möchten, ist dies einfacher:

SELECT whatever FROM table WHERE id=13

als SELECT was auch immer FROM-Tabelle WHERE col1 = 'val1' AND col2 = 'val2' AND col3 = 'val3'

In einer Webanwendung bedeutet dies beispielsweise, dass die URL folgendermaßen aussieht:

www.somewebsite.com/somepage.php?id=13

oder so:

www.somewebsite.com/somepage.php?col1=val1&col2=val2&col3=val3
Infrarot
quelle
4
Und es ist viel einfacher, eine verknüpfte Tabelle hinzuzufügen, wenn Sie eine
ID
3
Sorry, an dieser Stelle muss ich -1, da A) es nicht schwarz und weiß ist. Das Hinzufügen einer ID-Spalte beinhaltet Negative, wie z. B. wo und wann Sie diese neue ID generieren. Darüber hinaus kann es zu zusätzlichen Verknüpfungen oder SELECTAbfragen kommen. Und, B) , ich habe keine Ahnung, wie dies tatsächlich irgendeine Art von URL-Anforderung verursacht (es sei denn, Sie arbeiten mit einem schlechten Framework). Meine URLs enthalten keine Abfragezeichenfolgen ?id=13, geschweige denn ?col1=val1&col2=val2&col3=val3.
Nicole
2
@renesis: Diese Site enthält eindeutige Fragen und Benutzer, die in den URLs enthalten sind. Dies ist jedoch ein Sonderfall, da sich diese Daten nicht ändern.
Michael K
1
@Renesis, die meisten (vielleicht alle) modernen DBs haben auto_increment Integer-Spaltentypen, mit denen die IDs automatisch und sicher generiert und per SQL-Abfrage oder Bibliotheksfunktionsaufruf zurückgemeldet werden können. Oder Sie verwenden in einer verteilten Umgebung einen großen zufälligen Hash. Einige DBs erstellen sogar eine versteckte ID-Spalte für Sie, wenn Sie noch keine in der Tabelle haben.
GroßmeisterB
@Michael - Ich habe nicht gesagt, dass IDs niemals in URLs enthalten sind. Natürlich sind sie. Wenn Sie URLs haben, die eine Reihe von Daten darstellen, sollten diese Daten wahrscheinlich eine eindeutige ID haben. Es sei denn, ein anderer Teil der URL enthält bereits die anderen Teile des Mehrfachschlüssels. @GrandmasterB Weder die beiden letzten Unternehmen, für die ich gearbeitet habe (über 6 Jahre), die beide MySQL verwenden (eines unterstützt auch Oracle und SQL Server), konnten Auto-Increment verwenden, noch einen großen zufälligen Hash.
Nicole
8

Grundsätzlich werden Sie gefragt, ob Sie Ersatz- oder natürliche Schlüssel verwenden sollen (in Ihrem Fall klingt dies nach zusammengesetzten natürlichen Schlüsseln). Hier ist ein großartiger Artikel: http://www.agiledata.org/essays/keys.html

Ich bevorzuge Ersatzschlüssel, weil sie die Verwaltung über die gesamte Lebensdauer der Datenbank vereinfachen (Sie müssen sich keine Gedanken darüber machen, wie sich die Bedeutung von Schlüsseln ändert, was in keinem realen System, in dem Menschen involviert sind, passieren sollte). Allerdings , wenn es eine Menge von „Lookup“ Tabellen in der DB ist (dh Tabellen , die im Grunde sind die Schlüssel: Wert - Paare), dann kann Ersatzschlüssel erhält umständlich , weil man diese Tabellen in die Abfrage verbinden , um muß aussagekräftige Ergebnisse zu erhalten.

Angenommen, Sie haben zwei Entitäten: Adresse und Land.

  • Die Beziehung lautet: Adresse * ----- 1 Land
  • Die Entität Country ist im Grunde genommen ein Schlüssel-Wert-Paar (z. B. US: USA, CA: Kanada, MX: Mexiko usw.).
  • So fragen Sie diese Struktur für alle Adressen in den USA ab:

select * from Address where CountryCode = 'US'

  • So führen Sie dieselbe Abfrage mit Ersatzschlüsseln durch:

select Address.* from Address join Country on Address.CountryID = Country.ID where Country.Code = 'US'

Ich gebe gerne natürliche Schlüssel für Nachschlagetabellen und Ersatzschlüssel für alles andere an, wenn ich mir ziemlich sicher bin, dass sich die natürlichen Schlüssel nicht allzu oft ändern, wenn überhaupt.

Curtis Batt
quelle
5

Es hängt davon ab, wie Sie auf die Daten zugreifen. Wenn Sie häufig nach Teilschlüsseln suchen (wobei Sie Datensätze beispielsweise nur anhand von zwei der drei Schlüssel auswählen), sollten Sie die mehrteiligen Schlüssel beibehalten. OTOH, wenn Sie viele 1: 1-Beziehungen zu anderen Tabellen haben, ist es wahrscheinlich sinnvoller, einen Ersatzschlüssel zu haben.

TMN
quelle
1

Ich möchte immer einen Ersatzprimärschlüssel für jede Tabelle haben. Aber es gibt nicht viele "harte" Gründe, dies durchzusetzen, die ich gehört habe.

Das einzige Mal, dass ich jemals einen mehrspaltigen natürlichen Schlüsselbiss hatte, war mit ORM. Gelegentlich hatte ich Probleme mit einem mehrspaltigen Primärschlüssel, der Linq To Entities verwendet.

Mike M.
quelle
1

Sag niemals nie, aber es ist schmerzhaft, an 4 Säulen teilzunehmen. Je mehr Spalten mit intelligenten Daten vorhanden sind, desto größer ist die Wahrscheinlichkeit, dass sich diese Werte ändern. Datenbanken können so eingerichtet werden, dass die referenzielle Integrität bei kaskadierenden Updates erhalten bleibt.

Sie können jederzeit einen anderen Index erstellen, um die eindeutigen Werte zu verarbeiten.

Die Leistung ist in den meisten Fällen wahrscheinlich vernachlässigbar, aber Sie können Ihre Abfragen mit und ohne Ersatzschlüssel testen.

JeffO
quelle
0

Ich finde es schwierig, einen guten Grund zu finden, einen separaten Schlüssel zu vergeben, aber wie Sie sagten, haben viele Leute ihn eingegeben.

Ich finde das nicht hilfreich (besonders beim Speichern), wenn ich mit Fakten- / Detailtabellen arbeite. Ein kanonisches Beispiel für eine Verkaufsfaktentabelle mit einem (customer_key, store_key, product_key) mit Menge ist nicht sehr sinnvoll, um einen Schlüssel auf Datensatzebene zu haben.

Jé Queue
quelle
0

Wenn Sie feststellen, dass Ihr zusammengesetzter Schlüssel tatsächlich Duplikate haben kann, ist es einfacher, wenn PK ein Autoincrement Int ist.

Paul Nathan
quelle
0

Auf Ask Tom gibt es eine gute Diskussion, die bis ins Jahr 2002 zurückreicht . Es ist Oracle-spezifisch, aber die breitere Diskussion ist relevant, egal welche Datenbank Sie verwenden.

Rhys Gibson
quelle