Namenskonvention für Primärschlüssel / Fremdschlüssel [geschlossen]


95

In unserer Entwicklergruppe führen wir eine heftige Debatte über die Namenskonvention für Primär- und Fremdschlüssel. Grundsätzlich gibt es in unserer Gruppe zwei Denkschulen:

1:

Primary Table (Employee)   
Primary Key is called ID

Foreign table (Event)  
Foreign key is called EmployeeID

oder

2:

Primary Table (Employee)  
Primary Key is called EmployeeID

Foreign table (Event)  
Foreign key is called EmployeeID

Ich bevorzuge es, den Namen der Tabelle in keiner der Spalten zu duplizieren (daher bevorzuge ich Option 1 oben). Konzeptionell stimmt es mit vielen empfohlenen Vorgehensweisen in anderen Sprachen überein, in denen Sie den Namen des Objekts nicht in seinen Eigenschaftsnamen verwenden. Ich denke, dass die Benennung des Fremdschlüssels EmployeeID(oder Employee_IDbesser) dem Leser sagt, dass es sich um die IDSpalte der EmployeeTabelle handelt.

Einige andere bevorzugen Option 2, bei der Sie den Primärschlüssel mit dem Präfix "Tabellenname" benennen, damit der Spaltenname in der gesamten Datenbank identisch ist. Ich sehe diesen Punkt, aber Sie können jetzt einen Primärschlüssel nicht visuell von einem Fremdschlüssel unterscheiden.

Ich denke auch, dass es überflüssig ist, den Tabellennamen im Spaltennamen zu haben, denn wenn Sie die Tabelle als Entität und eine Spalte als Eigenschaft oder Attribut dieser Entität betrachten, betrachten Sie sie als ID-Attribut der Employee, nicht das EmployeeIDAttribut eines Mitarbeiters. Ich gehe nicht und frage meinen Kollegen, was sein PersonAgeoder PersonGenderist. Ich frage ihn, wie alt er ist.

Wie ich schon sagte, es ist eine heftige Debatte und wir gehen weiter und weiter und weiter darüber. Ich bin daran interessiert, neue Perspektiven zu bekommen.



1
Ich habe mehr als 10 ähnliche Fragen gelesen und schließlich festgestellt, dass die drei besten Antworten hier gut sind: stackoverflow.com/a/465146/781695
Benutzer

Nur eine Randnotiz: Mit Auswahl 2 können Sie 'Natural Join' durchführen. Heck, warum nicht immer noch in Auswahl 1, indem Sie 'Employee.ID als EmployeeID' hinzufügen. Die bessere Vorgehensweise scheint jedoch "Beitreten" mit "ON Employee.ID = Event.EmployeeID" zu sein.
Leo

In beiden Situationen müssen Sie in einer oder mehreren Warteschlangen einen Alias ​​(oder 'table_name.column_name') verwenden, da Sie in beiden Fällen Spaltennamen wiederholen.
Please_Dont_Bully_Me_SO_Lords

Antworten:


52

Es ist nicht wirklich wichtig. Ich bin noch nie auf ein System gestoßen, bei dem es einen echten Unterschied zwischen Wahl 1 und Wahl 2 gibt.

Jeff Atwood hatte vor einiger Zeit einen großartigen Artikel zu diesem Thema. Grundsätzlich diskutieren und argumentieren die Menschen am heftigsten über die Themen, bei denen sie sich nicht als falsch erweisen können. Oder aus einem anderen Blickwinkel, jene Themen, die nur durch ausdauernde Argumente im Filibuster-Stil gewonnen werden können.

Wählen Sie eine aus und fordern Sie sie auf, sich auf Probleme zu konzentrieren, die sich tatsächlich auf Ihren Code auswirken.

BEARBEITEN: Wenn Sie Spaß haben möchten, lassen Sie sie ausführlich angeben, warum ihre Methode für rekursive Tabellenreferenzen überlegen ist.


26
+1, für den gesunden Menschenverstand ... Es gibt wichtigere Dinge, über die man streiten muss. Also mach es auf meine Weise (Wahl 2)
Charles Bretana

5
Und für selbstreferenzierende DRI müssen Sie, wenn es mehr als eine FK gibt, die auf dieselbe PK selbst verweist, beide "Standards" verletzen, da die beiden FK-Spalten nicht gleich benannt werden können ... z. B. EmployeeTable mit EmployeeId PK, SupervisorId FK, MentorId Fk, PartnerId FK usw. usw.
Charles Bretana

74

Wenn die beiden Spalten in beiden Tabellen denselben Namen haben (Konvention Nr. 2), können Sie die USING-Syntax in SQL verwenden, um Tippfehler und Boilerplate-Rauschen zu vermeiden:

SELECT name, address, amount
  FROM employees JOIN payroll USING (employee_id)

Ein weiteres Argument für Konvention Nr. 2 ist, dass das relationale Modell so entworfen wurde.

Die Bedeutung jeder Spalte wird teilweise durch Kennzeichnung mit dem Namen der entsprechenden Domäne vermittelt.


4
SQL-Syntax und -Semantik geben tatsächlich einen ziemlich guten Hinweis darauf, wie sie verwendet werden sollte. Beispiel: USING-Syntax bedeutet, dass Spalten mit derselben Domäne denselben Namen haben sollten. NULL = NULL -> NULL bedeutet, dass NULL "unbekannt" und nicht "nicht anwendbar" ist. ON UPDATE CASCADE bedeutet, dass Schlüssel nur eindeutig und nicht unveränderlich sein müssen.
Steven Huwig

6
Noch besser, es erlaubt dies : SELECT name, address, amount FROM employees NATURAL JOIN payroll.
Tag, wenn

5
Ich würde Natural Join nicht in bereitgestelltem Code verwenden, da es bei Schemaerweiterungen brittler ist. Aber für interaktive Abfragen ist es großartig.
Steven Huwig

3
+1 aber es gibt immer eine Ausnahme. Wenn Sie beispielsweise zwei Spalten in der Personalabrechnung haben, die beide Fremdschlüssel für den Mitarbeiter sind (ein Verweis auf die Person, die bezahlt wird, der zweite beispielsweise auf den Manager mit Budgetberechtigung). Wir können aber nicht beide Fremdschlüssel benennen employee_id.
Bill Karwin

1
Das Schlüsselwort "using" ist MySQL-spezifisch. Funktioniert leider nicht in T-SQL.
Birdus

12

Ich denke, es hängt davon ab, wie Ihre Bewerbung zusammengestellt ist. Wenn Sie ORM verwenden oder Ihre Tabellen zur Darstellung von Objekten entwerfen, ist Option 1 möglicherweise für Sie geeignet.

Ich mag es, die Datenbank als eigene Ebene zu codieren. Ich kontrolliere alles und die App ruft nur gespeicherte Prozeduren auf. Es ist schön, Ergebnismengen mit vollständigen Spaltennamen zu haben, insbesondere wenn viele Tabellen verknüpft und viele Spalten zurückgegeben werden. Bei diesem Anwendungstyp gefällt mir Option 2. Ich mag es wirklich, wenn Spaltennamen bei Verknüpfungen übereinstimmen. Ich habe an alten Systemen gearbeitet, bei denen sie nicht übereinstimmten, und es war ein Albtraum.


4
+1 für das Herausfinden von Verknüpfungen mit nicht übereinstimmenden Spaltennamen
Raj More

4
auf "alten Systemen" das Handicap von 8 Zeichen langen Namen, das viel mehr schmerzt als dies. Ich bin bereit, mich auf die Probe zu stellen und zu spekulieren, dass die PK mit dem Namen ID nicht die Hauptursache für den Albtraum in den alten Systemen war, mit denen Sie zu tun hatten. Auch "es saugte in alten Systemen" wird waaaaay zu oft in der Softwareentwicklung verwendet, insbesondere in Datenbanken. Ich sehe routinemäßig Leute, die eine bestimmte Praxis A rechtfertigen, basierend auf der Art und Weise, wie sie in ihrer Erfahrung mit einem DB-System funktioniert hat, das vor mehr als 10 Jahren veröffentlicht wurde.
Russell Steen

2
Die heutigen hochmodernen Anwendungen werden in ein paar Jahren alter Mist sein . Sie können die Benutzeroberfläche sogar neu schreiben oder die Daten auf einer anderen Plattform verwenden, aber Ihre Daten (einschließlich Ihrer Spaltennamen) müssen den Test der Zeit bestehen.
KM.

2
Also hätten die Leute vor 20 Jahren irgendwie Spaltennamen verwenden sollen, die heute Sinn machten, obwohl sie nur 8 Zeichen hatten? Die Datenspeicherformate haben sich in den letzten 20 Jahren drastisch geändert und werden sich in den nächsten 20 Jahren erneut ändern. Es gibt keine Möglichkeit nachzuweisen, dass Ihre Präferenz den Test der Zeit besser bestehen wird als die andere aufgeführte Methode. "Spaltennamen" können selbst "alter Mist" sein, wenn die Leute diese Diskussion in 20 Jahren führen, da sich unsere Fähigkeit zum Speichern und Bearbeiten von Daten verbessert. Tabellen sind ein menschliches Konstrukt, das Datenbeziehungen nicht perfekt darstellt ...
Russell Steen

1
Vielen Dank für die gut begründete intellektuelle Antwort.
Russell Steen

3

Keine der beiden Konventionen funktioniert in allen Fällen. Warum also überhaupt eine? Verwenden Sie den gesunden Menschenverstand ...

Wenn es beispielsweise für eine selbstreferenzierende Tabelle mehr als eine FK-Spalte gibt, die auf die PK derselben Tabelle selbst verweist, MÜSSEN Sie beide "Standards" verletzen, da die beiden FK-Spalten nicht gleich benannt werden können ... z , EmployeeTable mit EmployeeId PK, SupervisorId FK, MentorId Fk, PartnerId FK, ...


1
+1 für die tatsächliche Antwort auf das technische Ziel
DVK

Eine gute, zutreffende Antwort, aber die Argumente zu Dems 'Antwort verfehlen den Punkt.
JYelton

3

Ich stimme zu, dass es wenig zu wählen gibt. Für mich ist der "Standard" -Teil eine viel wichtigere Sache bei beiden Standards.

Wenn Leute anfangen, "ihr eigenes Ding zu machen", sollten sie von ihren Nether gefesselt werden. MEINER BESCHEIDENEN MEINUNG NACH :)


3
+1 für das Erkennen, dass Konsistenz wichtiger ist als "richtig" zu sein (in diesem Fall)
Russell Steen

-1 für den Versuch, eine "dumme Konsistenz" anzuwenden. Das alte chinesische Sprichwort sagt: "Eine dumme Konsequenz ist ein Hobgoblin für einfache Köpfe."
Charles Bretana

@charles: In einer Welt, in der verschiedene Personen sich gegenseitig den Code pflegen, oft wenn der Autor gegangen ist und die Dokumentation veraltet oder nicht vorhanden ist, ist dies keine dumme Konsistenz. Ich bin so froh, dass ich nicht mit dir zusammenarbeite ...
MatBailie

@Dems, keine Straftat beabsichtigt, aber das ist aus zwei Gründen dumm. 1) Es gibt gängige, klar verstandene Szenarien, in denen JEDER Standard verletzt werden müsste. (siehe meine Antwort für Beispiele und 2), weil zumindest in dieser Frage ein Standard nur einen sehr geringen Mehrwert
bringt

1
Sie könnten argumentieren, dass "ID" konsistenter ist - denn sobald Sie die englische Sprache "carID" in die Tabelle "Autos" oder "Auto" einführen? "Schaf-ID" in "Schaf" -Tabelle oder "Schafe" - die Dinge beginnen inkonsistent zu werden. Wenn Sie sich an "ID" und einzelne Tabellennamen halten - dies ist nicht nur konsistent, sondern spielt auch gut mit vielen ORMs / erfordert auch weniger Konfiguration (z. B. Dapper Contrib)
Niico

3

Haben Sie Folgendes berücksichtigt?

Primary Table (Employee)   
Primary Key is PK_Employee

Foreign table (Event)  
Foreign key is called FK_Employee

3
Ich kann es nicht ertragen, wenn Leute abstimmen und keinen Grund dafür angeben. Dies ist eine völlig gültige Antwort. Ob es für manche schmackhaft ist oder nicht, ist eine andere Frage, aber das ist subjektiv und erfordert keine Abwertung.
Jeremy

1
Vielen Dank für den Hinweis. Mich würden auch die Gründe interessieren, warum Sie dieses Format nicht verwenden würden . Und ich bin mir ziemlich sicher, dass es gute Gründe geben wird ...
Wouter

Dies ist der beste Ausweg, da Sie ihn nicht table_name.column_namein Abfragen verwenden müssen und keinen Alias ​​für Spaltennamen verwenden müssen, wenn Sie keine wiederholten Namen haben ...
Please_Dont_Bully_Me_SO_Lords

1
Dies könnte als eine Form der ungarischen Notation angesehen werden. Betrachten Sie also die Argumente dafür und dagegen.
Fred

2

Die Konvention, die wir bei meiner Arbeit verwenden, liegt ziemlich nahe bei A, mit der Ausnahme, dass wir Tabellen im Plural benennen (dh "Mitarbeiter") und Unterstriche zwischen dem Tabellen- und Spaltennamen verwenden. Der Vorteil davon ist, dass für den Verweis auf eine Spalte entweder "employee _ id" oder "employee.id" angegeben wird, je nachdem, wie Sie darauf zugreifen möchten. Wenn Sie angeben müssen, aus welcher Tabelle die Spalte stammt, ist "employee.employees _ id" definitiv redundant.


Ich habe mich nicht entschieden, ob ich pluralisierte Tabellennamen mag. Durch die Verwendung des Singulars scheinen die Abfragen besser zu lesen ("employee.name" im Gegensatz zu "employee.name"). Selbst bei Verknüpfungen scheint es besser zu lesen, wenn Sie einzelne Datensätze mit einer anderen Tabelle verknüpfen. Pluralisierte Tabellennamen scheinen jedoch genauer zu sein, wenn man an die Tabelle denkt, als an die Abfrage. Ich werde bei Singular bleiben, da dies das ist, was wir verwenden, aber ich denke, es ist auch der richtige Weg (obwohl auch hier viele anderer Meinung sind)
MatBailie

Ja. Es ist eher eine persönliche Präferenz und / oder was auch immer Sie gewohnt sind zu sehen, denke ich.
Jarett Millard

2

Wenn Sie sich den Anwendungscode und nicht nur Datenbankabfragen ansehen, scheinen mir einige Dinge klar zu sein:

  1. Tabellendefinitionen werden normalerweise direkt einer Klasse zugeordnet, die ein Objekt beschreibt. Sie sollten daher singulär sein. Um eine Sammlung eines Objekts zu beschreiben, füge ich normalerweise "Array" oder "Liste" oder "Sammlung" an den singulären Namen an, da dies deutlicher als die Verwendung von Pluralformen nicht nur anzeigt, dass es sich um eine Sammlung handelt, sondern auch um welche Art von Sammlung es ist. In dieser Ansicht sehe ich einen Tabellennamen nicht als den Namen der Sammlung, sondern als den Namen des Objekttyps, von dem es sich um eine Sammlung handelt. Ein DBA, der keinen Anwendungscode schreibt, könnte diesen Punkt übersehen.

  2. Die Daten, mit denen ich mich beschäftige, verwenden häufig "ID" zur Identifizierung ohne Schlüssel. Um Verwechslungen zwischen Schlüssel- "IDs" und Nicht-Schlüssel- "IDs" zu vermeiden, verwenden wir für den Primärschlüsselnamen "Schlüssel" (das ist es, nicht wahr?), Dem der Tabellenname oder eine Abkürzung von vorangestellt ist der Tabellenname. Dieses Präfix (und ich reserviere dies nur für den Primärschlüssel) macht den Schlüsselnamen eindeutig, was besonders wichtig ist, da wir Variablennamen verwenden, die mit den Namen der Datenbankspalten identisch sind, und die meisten Klassen ein übergeordnetes Element haben, das durch den Namen von identifiziert wird der übergeordnete Schlüssel. Dies ist auch erforderlich, um sicherzustellen, dass es sich nicht um ein reserviertes Schlüsselwort handelt, sondern nur um "Schlüssel". Um die Konsistenz der wichtigsten Variablennamen zu erleichtern und Programme bereitzustellen, die natürliche Verknüpfungen ausführen, Fremdschlüssel haben denselben Namen wie in der Tabelle, in der sie der Primärschlüssel sind. Ich bin mehr als einmal auf Programme gestoßen, die auf diese Weise mit natürlichen Verknüpfungen viel besser funktionieren. In diesem letzten Punkt gebe ich ein Problem mit selbstreferenzierenden Tabellen zu, die ich verwendet habe. In diesem Fall würde ich eine Ausnahme von der Fremdschlüssel-Namensregel machen. Zum Beispiel würde ich ManagerKey als Fremdschlüssel in der Employee-Tabelle verwenden, um auf einen anderen Datensatz in dieser Tabelle zu verweisen.


Bei vielen objektrelationalen Mappern (ORM) wie Entity Framework können Sie eine Tabelle einer Klasse mit einem anderen Namen zuordnen. Auf diese Weise können Sie eine Klasse mit dem Namen "Benutzer" und eine Tabelle mit dem Namen "Benutzer" erstellen.
Fred

2

Ich mag Konvention Nr. 2 - als ich dieses Thema recherchierte und diese Frage fand, bevor ich meine eigene veröffentlichte, stieß ich auf das Problem, bei dem:

Ich wähle * aus einer Tabelle mit einer großen Anzahl von Spalten aus und verbinde sie mit einer zweiten Tabelle, die ebenfalls eine große Anzahl von Spalten enthält. Beide Tabellen haben eine "id" -Spalte als Primärschlüssel, und das bedeutet, dass ich jede Spalte (soweit ich weiß) spezifisch auswählen muss, um diese beiden Werte im Ergebnis eindeutig zu machen, dh:

SELECT table1.id AS parent_id, table2.id AS child_id

Obwohl die Verwendung von Konvention Nr. 2 bedeutet, dass das Ergebnis immer noch einige Spalten mit demselben Namen enthält, kann ich jetzt angeben, welche ID ich benötige (Eltern oder Kind), und wie Steven Huwig vorgeschlagen hat, USINGvereinfacht die Anweisung die Dinge weiter.


2
SELECT *ist sowieso ein Nein-Nein für (die meisten) Produktionsanfragen, daher ist dies kein guter Grund, einen Namensstandard zu wählen.
P Daddy

1
Nicht anderer Meinung: Können Sie einen Link zu einem Grund angeben, warum dies so ist? Ich mag die Idee nicht, die Namen von 80 Spalten in meiner Abfrage pflegen zu müssen.
JYelton

Ich kann im Moment keinen Link finden (schwer zu googeln für "*"), aber ich werde die grundlegenden Punkte skizzieren: (1) Änderungen an den Tabellen können sich negativ auf Ihre Anwendung auswirken, (2) es kann sein Schlechte Leistung und (3) explizite Angabe der tatsächlich benötigten Daten kann das Verständnis Ihres Codes erleichtern. Diese Punkte könnten erweitert werden, und es gibt Ausnahmen (wie ich angedeutet habe), aber das ist hier nicht angemessen. Wenn Sie dies als neue Frage posten, würde ich (und andere) gerne weiter darauf eingehen.
P Daddy

2
Ich kann das machen. Ich erkenne den Leistungsvorteil, muss aber den Zeitaufwand beim Bearbeiten von Code berücksichtigen. Ich bin immer auf der Suche nach Möglichkeiten, die Interaktion zwischen der App und der Datenbank zu verbessern. Vielen Dank.
JYelton

1
Ich bin mir nicht sicher, ob dies SELECT *für die meisten Produktionsanfragen ein Nein-Nein ist. Wenn es Ihre Entwicklungsgeschwindigkeit erheblich erhöht und Ihren Code viel knapper und lesbarer macht - so dass Sie sich auf wichtigere Dinge konzentrieren können - warum nicht SELECT *? Es hängt sehr stark von den Umständen jeder Situation ab und ist ein Kompromiss zwischen vielen Faktoren. Eine Regel passt selten zu allem.
Niico

2

Ich habe immer userId als PK für eine Tabelle und userId für eine andere Tabelle als FK verwendet. Ich denke ernsthaft darüber nach, userIdPK und userIdFK als Namen zu verwenden, um sie voneinander zu unterscheiden. Es wird mir helfen, PK und FK beim Betrachten der Tabellen schnell zu identifizieren, und es scheint, als würde es den Code aufklären, wenn PHP / SQL für den Zugriff auf Daten verwendet wird, um das Verständnis zu erleichtern. Besonders wenn jemand anderes meinen Code ansieht.


1

Ich benutze Konvention # 2. Ich arbeite jetzt mit einem alten Datenmodell, bei dem ich nicht weiß, wofür in einer bestimmten Tabelle steht. Wo ist der Schaden, wenn man wortreich ist?


1

Wie wäre es mit der Benennung des Fremdschlüssels?

role_id

Dabei ist Rolle die Rolle, die die referenzierte Entität relativ zur vorliegenden Tabelle hat. Dies löst das Problem der rekursiven Referenz und mehrerer fks auf dieselbe Tabelle.

In vielen Fällen ist der Name der referenzierten Tabelle identisch. In diesem Fall wird es identisch mit einem Ihrer Vorschläge.

Auf jeden Fall ist es eine schlechte Idee, lange Argumente zu haben


0

"Wo in" Mitarbeiter INNER JOIN order ON order.employee_id = employee.id "besteht Bedarf an zusätzlicher Qualifikation?".

Es ist keine zusätzliche Qualifikation erforderlich, da die Qualifikation, von der ich gesprochen habe, bereits vorhanden ist.

"Der Grund, warum ein Geschäftsbenutzer auf die Auftrags-ID oder die Mitarbeiter-ID verweist, besteht darin, den Kontext anzugeben. Auf Datenbankebene haben Sie jedoch bereits einen Kontext, weil Sie sich auf die Tabelle beziehen."

Beten Sie, sagen Sie mir, wenn die Spalte den Namen "ID" trägt, wie wird dann das "Verweisen auf die Tabelle" genau durchgeführt, es sei denn, Sie qualifizieren diesen Verweis auf die ID-Spalte genau so, wie ich es erwähnt habe?

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.