Convention de dénomination de la clé primaire / clé étrangère [fermé]

95

Dans notre groupe de développement, nous avons un débat acharné concernant la convention de dénomination des clés primaires et étrangères. Il y a essentiellement deux écoles de pensée dans notre groupe:

1:

Primary Table (Employee)   
Primary Key is called ID

Foreign table (Event)  
Foreign key is called EmployeeID

ou

2:

Primary Table (Employee)  
Primary Key is called EmployeeID

Foreign table (Event)  
Foreign key is called EmployeeID

Je préfère ne pas dupliquer le nom de la table dans aucune des colonnes (donc je préfère l'option 1 ci-dessus). Conceptuellement, il est cohérent avec de nombreuses pratiques recommandées dans d'autres langues, où vous n'utilisez pas le nom de l'objet dans ses noms de propriété. Je pense que nommer la clé étrangère EmployeeID(ou Employee_IDpourrait être mieux) indique au lecteur que c'est la IDcolonne de la Employeetable.

D'autres préfèrent l'option 2 où vous nommez la clé primaire avec le préfixe du nom de la table afin que le nom de la colonne soit le même dans toute la base de données. Je vois ce point, mais vous ne pouvez plus distinguer visuellement une clé primaire d'une clé étrangère.

De plus, je pense qu'il est redondant d'avoir le nom de la table dans le nom de la colonne, car si vous considérez la table comme une entité et une colonne comme une propriété ou un attribut de cette entité, vous la considérez comme l'attribut ID du Employee, pas l' EmployeeIDattribut d'un employé. Je ne vais pas demander à mon collègue ce qu'il estPersonAge ou PersonGenderest. Je lui demande quel est son âge.

Donc, comme je l'ai dit, c'est un débat qui fait rage et nous continuons encore et encore à ce sujet. Je suis intéressé à avoir de nouvelles perspectives.

Jérémie
la source
1
question duplique cette stackoverflow.com/questions/208580/…
Mike Henke
1
J'ai lu plus de 10 questions similaires et j'ai finalement trouvé que les 3 premières réponses sont bonnes: stackoverflow.com/a/465146/781695
utilisateur
Juste une remarque: le choix 2 vous permettrait de «joindre naturellement». Heck, pourquoi ne pas toujours le faire dans le choix 1 en ajoutant «Employee.ID as EmployeeID». Mais la meilleure méthode semble être «Rejoindre» en utilisant «ON Employee.ID = Event.EmployeeID».
Leo
Dans les deux cas, vous devrez et plus devoir utiliser un alias (ou 'table_name.column_name') dans une ou plusieurs queires parce que vous répétez dans les deux cas les noms de colonnes.
Please_Dont_Bully_Me_SO_Lords

Réponses:

52

Cela n'a pas vraiment d'importance. Je n'ai jamais rencontré un système où il y a une réelle différence entre le choix 1 et le choix 2.

Jeff Atwood a publié un excellent article il y a quelque temps sur ce sujet. Fondamentalement, les gens débattent et argumentent le plus furieusement sur les sujets sur lesquels on ne peut pas prouver qu'ils ont tort. Ou sous un angle différent, ces sujets qui ne peuvent être gagnés que par le biais d'arguments du dernier homme debout.

Choisissez-en un et dites-leur de se concentrer sur les problèmes qui ont réellement un impact sur votre code.

EDIT: Si vous voulez vous amuser, demandez-leur de spécifier longuement pourquoi leur méthode est supérieure pour les références de table récursives.

Russell Steen
la source
26
+1, pour le bon sens ... Il y a des choses plus importantes à discuter .. Alors, fais-le à ma façon (choix 2)
Charles Bretana
5
Et, pour le DRI auto-référencé, quand il y a plus d'un FK qui auto-référence le même PK, vous DEVEZ violer les deux "standards", puisque les deux colonnes FK ne peuvent pas être nommées de la même manière ... par exemple EmployeeTable avec EmployeeId PK, SupervisorId FK, MentorId Fk, PartnerId FK, etc. etc ...
Charles Bretana
75

Si les deux colonnes ont le même nom dans les deux tables (convention n ° 2), vous pouvez utiliser la syntaxe USING dans SQL pour enregistrer un peu de frappe et un peu de bruit standard:

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

Un autre argument en faveur de la convention n ° 2 est que c'est la façon dont le modèle relationnel a été conçu.

La signification de chaque colonne est partiellement véhiculée en l'étiquetant avec le nom du domaine correspondant.

Steven Huwig
la source
4
La syntaxe et la sémantique SQL donnent en fait une assez bonne idée de la façon dont elle doit être utilisée. Par exemple, la syntaxe USING signifie que les colonnes avec le même domaine doivent avoir le même nom, NULL = NULL -> NULL signifie que NULL est "inconnu" plutôt que "non applicable", et ON UPDATE CASCADE signifie que les clés doivent être uniques et non immuables.
Steven Huwig
6
Mieux encore, il permet ceci: SELECT name, address, amount FROM employees NATURAL JOIN payroll.
jour du
5
Je n'utiliserais pas de jointure naturelle dans le code déployé, car c'est plus fragile dans le cas des ajouts de schéma. Mais pour les requêtes interactives, c'est génial.
Steven Huwig
3
+1 mais il y a toujours une exception. Par exemple, si vous avez deux colonnes dans la paie qui sont toutes deux des clés étrangères pour l'employé (une référence à la personne qui est payée, la seconde au responsable disposant de l'autorisation budgétaire, par exemple). Mais nous ne pouvons pas nommer les deux clés étrangères employee_id.
Bill Karwin
1
Le mot-clé "using" est spécifique à MySql. Ne fonctionne pas dans T-SQL - malheureusement.
birdus
12

Je pense que cela dépend de la manière dont votre candidature est élaborée. Si vous utilisez ORM ou concevez vos tableaux pour représenter des objets, l'option 1 peut être pour vous.

J'aime coder la base de données comme sa propre couche. Je contrôle tout et l'application n'appelle que les procédures stockées. Il est agréable d'avoir des ensembles de résultats avec des noms de colonnes complets, en particulier lorsqu'il y a de nombreuses tables jointes et de nombreuses colonnes renvoyées. Avec ce type d'application, j'aime l'option 2. J'aime vraiment voir les noms de colonnes correspondre sur les jointures. J'ai travaillé sur d'anciens systèmes où ils ne correspondaient pas et c'était un cauchemar,

KM.
la source
4
+1 pour avoir à trouver des jointures avec des noms de colonnes non correspondants
Raj More
4
sur les "anciens systèmes", le handicap des noms longs de 8 caractères qui fait beaucoup plus mal que cela. Je suis prêt à sortir sur une branche et à spéculer que le fait d'avoir l'ID nommé PK n'était pas la principale cause du cauchemar dans les anciens systèmes avec lesquels vous traitez. Aussi "il aspirait dans les anciens systèmes" est utilisé trop souvent dans le développement de logiciels, en particulier les bases de données. Je vois régulièrement des gens justifier une pratique A donnée, en fonction de la façon dont cela a fonctionné dans leur expérience sur un système de base de données sorti il ​​y a plus de 10 ans.
Russell Steen
2
Les applications de pointe d'aujourd'hui seront de la vieille merde dans quelques années. vous pourriez même réécrire l'interface ou utiliser les données sur une autre plate-forme, mais vos données (y compris vos noms de colonnes) devront résister à l'épreuve du temps.
KM.
2
Il y a 20 ans, les gens auraient donc dû utiliser des noms de colonnes qui avaient du sens aujourd'hui, même s'ils n'avaient que 8 caractères? Les formats de stockage de données ont radicalement changé au cours des 20 dernières années et changeront à nouveau dans les 20 prochaines années. Il n'y a aucun moyen de démontrer que votre préférence résistera mieux à l'épreuve du temps que l'autre méthode répertoriée. Les "noms de colonnes" peuvent eux-mêmes être de "vieilles conneries" au moment où les gens auront cette discussion dans 20 ans, car notre capacité à stocker et à manipuler des données s'améliorera. Les tableaux sont une construction humaine qui représente imparfaitement les relations de données ...
Russell Steen
1
Merci pour la réponse intellectuelle bien raisonnée.
Russell Steen
3

Aucune des deux conventions ne fonctionne dans tous les cas, alors pourquoi en avoir une? Utiliser le bon sens...

par exemple, pour une table auto-référencée, quand il y a plus d'une colonne FK qui auto-référence le PK de la même table, vous DEVEZ violer les deux "standards", puisque les deux colonnes FK ne peuvent pas être nommées de la même manière ... par exemple , EmployeeTable avec EmployeeId PK, SupervisorId FK, MentorId Fk, PartnerId FK, ...

Charles Bretana
la source
1
+1 pour la réponse objective technique réelle
DVK
Une bonne réponse applicable, mais les arguments à la réponse de Dems manquent le point.
JYelton
3

Je reconnais qu'il y a peu de choix entre eux. Pour moi, une chose beaucoup plus importante à propos de l'une ou l'autre norme est la partie «standard».

Si les gens commencent à «faire leur propre chose», ils devraient être bloqués par leurs nethers. A MON HUMBLE AVIS :)

MatBailie
la source
3
+1 pour avoir reconnu que la cohérence est plus importante que d'avoir «raison» (dans ce cas)
Russell Steen
-1 pour avoir tenté d'appliquer une "cohérence stupide". Le vieux proverbe chinois dit: "Une cohérence insensée est un hobgobelin pour les esprits simples."
Charles Bretana
@charles: dans un monde où différentes personnes se maintiennent mutuellement du code, souvent lorsque l'écrivain est parti et que la documentation est obsolète ou inexistante, ce n'est pas une cohérence stupide. Je suis tellement content de ne pas travailler avec toi ...
MatBailie
@Dems, aucune infraction prévue, mais c'est insensé, pour deux raisons. 1) Il existe des scénarios communs et clairement compris dans lesquels TOUTE norme DEVRAIT être violée. (voir ma réponse pour des exemples et 2) parce que sur cette question, au moins, une norme ajouterait très peu de valeur, sauf pour que les gens qui aiment les normes se sentent plus à l'aise ...
Charles Bretana
1
vous pourriez dire que "ID" est plus cohérent - parce que dès que vous introduisez la langue anglaise "carID" dans le tableau "cars" ou "car" table? «SheepID» dans le tableau «moutons» ou «moutons» - les choses commencent à devenir incohérentes. Si vous vous en tenez à "ID" et aux noms de tables au singulier - ce n'est pas seulement cohérent, c'est bien joué avec de nombreux ORM / nécessite moins de configuration aussi (par exemple Dapper Contrib)
niico
3

Avez-vous envisagé ce qui suit?

Primary Table (Employee)   
Primary Key is PK_Employee

Foreign table (Event)  
Foreign key is called FK_Employee
Wouter
la source
3
Je ne peux pas supporter que les gens votent et je ne donne aucune raison. C'est une réponse tout à fait valable, qu'elle soit acceptable ou non pour certains est une question différente, mais qui est subjective et ne nécessite pas un vote défavorable.
Jeremy
1
Merci de l'avoir signalé. Je serais également intéressé par les raisons pour lesquelles vous n'utiliseriez pas ce format. Et je suis sûr qu'il y aura de bonnes raisons ...
Wouter
C'est le meilleur moyen de sortir car vous n'aurez pas à utiliser table_name.column_namedans les requêtes et n'aurez pas à utiliser d'alias pour les noms de colonne si vous n'avez pas de noms répétés ...
Please_Dont_Bully_Me_SO_Lords
1
Cela pourrait être considéré comme une forme de notation hongroise. Alors considérez les arguments pour et contre cela.
Fred
2

La convention que nous utilisons là où je travaille est assez proche de A, à l'exception du fait que nous nommons les tables au pluriel (c'est-à-dire «employés») et utilisons des traits de soulignement entre le nom de la table et de la colonne. L'avantage est que pour faire référence à une colonne, il s'agit soit de "employee _ id" soit de "Employees.id", selon la manière dont vous souhaitez y accéder. Si vous avez besoin de spécifier de quelle table provient la colonne, "Employees.employees _ id" est définitivement redondant.

Jarett Millard
la source
Je n'ai pas décidé si j'aime les noms de tables au pluriel. En utilisant le singulier, les requêtes semblent mieux lire («employé.nom» par opposition à «employés.nom»). Même dans les jointures, il semble mieux lire lorsque vous joignez des enregistrements uniques à une autre table. Mais les noms de table au pluriel semblent plus précis lorsque l'on pense à la table plutôt qu'à la requête. Je vais m'en tenir au singulier car c'est ce que nous utilisons, mais je pense que c'est aussi la bonne voie à suivre (bien qu'une fois encore, beaucoup ne soient pas d'accord)
MatBailie
Ouais. C'est plus une préférence personnelle et / ou tout ce que vous avez l'habitude de voir, je suppose.
Jarett Millard
2

Si vous regardez le code de l'application, pas seulement les requêtes de base de données, certaines choses me semblent claires:

  1. Les définitions de table correspondent généralement directement à une classe qui décrit un objet, elles doivent donc être au singulier. Pour décrire une collection d'un objet, j'ajoute généralement "Array" ou "List" ou "Collection" au nom singulier, car il indique plus clairement que l'utilisation de pluriels indique non seulement qu'il s'agit d'une collection, mais quel type de collection c'est. Dans cette vue, je vois un nom de table comme non pas le nom de la collection, mais le nom du type d'objet dont il est une collection. Un DBA qui n'écrit pas de code d'application peut manquer ce point.

  2. Les données que je traite utilisent souvent «ID» à des fins d'identification non essentielles. Pour éliminer la confusion entre les "ID" clés et les "ID" non clés, pour le nom de la clé primaire, nous utilisons "Key" (c'est ce que c'est, n'est-ce pas?) Avec le préfixe du nom de la table ou une abréviation de le nom de la table. Ce préfixe (et je le réserve uniquement pour la clé primaire) rend le nom de clé unique, ce qui est particulièrement important car nous utilisons des noms de variables identiques aux noms de colonnes de la base de données, et la plupart des classes ont un parent, identifié par le nom de la clé parent. Ceci est également nécessaire pour s'assurer qu'il ne s'agit pas d'un mot-clé réservé, ce que "Key" seul est. Pour faciliter la cohérence des noms de variables clés et fournir des programmes qui effectuent des jointures naturelles, les clés étrangères ont le même nom que celui utilisé dans la table dans laquelle elles sont la clé primaire. J'ai rencontré plus d'une fois des programmes qui fonctionnent beaucoup mieux de cette façon en utilisant des jointures naturelles. Sur ce dernier point, j'avoue un problème avec les tables d'auto-référencement, que j'ai utilisé. Dans ce cas, je ferais une exception à la règle de dénomination de clé étrangère. Par exemple, j'utiliserais ManagerKey comme clé étrangère dans la table Employee pour pointer vers un autre enregistrement de cette table.

Bruce Patin
la source
De nombreux mappeurs relationnels objet (ORM) tels que Entity Framework vous permettent de mapper une table à une classe avec un nom différent. Cela vous permet d'avoir une classe nommée "User" et une table nommée "Users".
Fred
2

J'aime la convention n ° 2 - en recherchant ce sujet et en trouvant cette question avant de publier la mienne, je suis tombé sur le problème où:

Je sélectionne * à partir d'une table avec un grand nombre de colonnes et je la joins à une deuxième table qui a de la même manière un grand nombre de colonnes. Les deux tables ont une colonne "id" comme clé primaire, ce qui signifie que je dois sélectionner spécifiquement chaque colonne (pour autant que je sache) afin de rendre ces deux valeurs uniques dans le résultat, c'est-à-dire:

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

Bien que l'utilisation de la convention n ° 2 signifie que j'aurai toujours des colonnes dans le résultat avec le même nom, je peux maintenant spécifier l' id dont j'ai besoin (parent ou enfant) et, comme Steven Huwig l'a suggéré, l' USINGinstruction simplifie encore les choses.

JYelton
la source
2
SELECT *est un non-non pour (la plupart) des requêtes de production, de toute façon, ce n'est donc pas une bonne raison de choisir une norme de dénomination.
P Daddy
1
Pas en désaccord: pourriez-vous fournir un lien vers une raison pour laquelle il en est ainsi? Je n'aime pas l'idée de devoir conserver les noms de 80 colonnes dans ma requête.
JYelton
Impossible de trouver un lien pour le moment (difficile à rechercher sur Google pour "*"), mais je vais souligner les points de base: (1) les modifications apportées au (x) tableau (s) peuvent avoir un impact négatif sur votre application, (2) cela peut être mauvais pour les performances, et (3) spécifier explicitement les données dont vous avez réellement besoin peut rendre votre code plus facile à comprendre. Ces points pourraient se développer, et il y a des exceptions (comme je l'ai mentionné) mais ce n'est pas approprié ici. Si vous postez ceci comme une nouvelle question, je (et d'autres) serions heureux de développer davantage.
P Daddy
2
Je peux faire ça. Je réalise l'avantage en termes de performances, mais je dois prendre en compte l'investissement en temps lors de l'édition du code. Je recherche toujours des moyens d'améliorer l'interaction entre l'application et la base de données. Merci.
JYelton
1
Je ne suis pas sûr que ce SELECT *soit un non-non pour la plupart des requêtes de production. Si cela augmente considérablement votre vitesse de développement et rend votre code beaucoup plus laconique et lisible - vous permettant de vous concentrer sur des questions plus importantes - pourquoi pas SELECT *? Cela dépend beaucoup des circonstances de chaque situation et constitue un compromis entre de nombreux facteurs. Une règle convient rarement à tout.
niico
2

J'ai toujours utilisé userId comme PK sur une table et userId sur une autre table comme FK. Je pense sérieusement à utiliser userIdPK et userIdFK comme noms pour identifier les uns des autres. Cela m'aidera à identifier PK et FK rapidement lorsque je regarde les tables et il semble que cela effacera le code lors de l'utilisation de PHP / SQL pour accéder aux données, ce qui facilitera la compréhension. Surtout quand quelqu'un d'autre regarde mon code.

Ross
la source
1

J'utilise la convention n ° 2. Je travaille maintenant avec un modèle de données hérité où je ne sais pas ce que signifie une table donnée. Où est le mal d'être verbeux?

Poneys OMG
la source
1

Que diriez-vous de nommer la clé étrangère

role_id

où role est le rôle de l'entité référencée par rapport à la table à portée de main. Cela résout le problème de la référence récursive et de plusieurs fks à la même table.

Dans de nombreux cas, sera identique au nom de la table référencée. Dans ce cas, il devient identique à l'une de vos propositions.

En tout cas, avoir de longs arguments est une mauvaise idée

Jens Schauder
la source
0

"Où dans" employé INNER JOIN order ON order.employee_id = employee.id "y a-t-il besoin d'une qualification supplémentaire?".

Il n'y a pas besoin de qualification supplémentaire car la qualification dont j'ai parlé est déjà là.

"la raison pour laquelle un utilisateur professionnel se réfère à l'ID de commande ou à l'ID d'employé est de fournir un contexte, mais au niveau de la base de données, vous avez déjà un contexte parce que vous référez à la table".

Je vous en prie, dites-moi, si la colonne est nommée «ID», alors comment se fait exactement ce «renvoi [sic] à la table», à moins de qualifier cette référence à la colonne ID exactement de la manière dont j'ai parlé?


la source