Schéma de dénomination des clés étrangères


153

Je commence tout juste à travailler avec des clés étrangères pour la première fois et je me demande s'il existe un schéma de dénomination standard à utiliser pour elles?

Compte tenu de ces tableaux:

task (id, userid, title)
note (id, taskid, userid, note);
user (id, name)

Là où les tâches ont des notes, les tâches appartiennent aux utilisateurs et les utilisateurs créent des notes.

Comment les trois clés étrangères seraient-elles nommées dans cette situation? Ou bien, est-ce vraiment important ?

Mise à jour : cette question concerne les noms de clés étrangères, pas les noms de champs!


6
Remarque pour les lecteurs: la plupart des bonnes pratiques répertoriées ci-dessous ne fonctionnent pas dans Oracle en raison de sa limite de 30 caractères. Un nom de table ou de colonne peut déjà contenir près de 30 caractères, donc une convention combinant les deux en un seul nom nécessite une norme de troncature ou d'autres astuces.
Charles Burns

Réponses:


180

La convention standard dans SQL Server est:

FK_ForeignKeyTable_PrimaryKeyTable

Ainsi, par exemple, la clé entre les notes et les tâches serait:

FK_note_task

Et la clé entre les tâches et les utilisateurs serait:

FK_task_user

Cela vous donne une vue "en un coup d'œil" des tables impliquées dans la clé, ce qui permet de voir facilement de quelles tables dépend une table particulière (la première nommée) (la seconde nommée). Dans ce scénario, l'ensemble complet de clés serait:

FK_task_user
FK_note_task
FK_note_user

Ainsi, vous pouvez voir que les tâches dépendent des utilisateurs et que les notes dépendent à la fois des tâches et des utilisateurs.


1
Si la clé étrangère pointe vers une clé candidate sur la deuxième table plutôt qu'une clé primaire, vous utiliserez probablement un troisième segment pour le nom pour qualifier cela. C'est une situation inhabituelle dans laquelle se trouver, et pas celle que vous concevez généralement à partir de zéro, donc je n'ai pas inclus cela dans la réponse.
Greg Beech

4
Vous incluez le nom de la table actuelle dans la clé pour la garder distincte. Les noms FK sont dans l'espace de noms global dans SQL Server, vous ne pouvez donc pas avoir deux FK nommées FK_PrimaryKeyTable attachées à deux tables de clés étrangères différentes. Les règles peuvent être différentes pour d'autres serveurs de base de données.
Greg Beech

D'accord ... J'ai différents espaces de noms pour chaque table dans Oracle, donc je n'ai pas besoin de l'auto-référence.
Steve Moyer

29
Cela semble être l'utilisation courante, mais que faire quand il y a deux clés étrangères pointant vers la même table. ie messagetable a un from_user_idet les to_user_iddeux deviendraient fk_message_user. Il me semble préférable d'utiliser fk_tablename_columnname(fk_message_from_user_id dans mon exemple) pour cette raison, puis d'essayer de garder les noms de vos colonnes clairs sur la table cible (c'est-à-dire que to_user_id fait clairement référence à la table des utilisateurs)
Code Commander

et si le tableau lui-même avait des traits de soulignement par exemple. user_role et user_addresses? fk_user_addresses_user_role n'est-ce pas déroutant?
Govi S

38

J'utilise deux caractères de soulignement comme délimiteur ie

fk__ForeignKeyTable__PrimaryKeyTable 

En effet, les noms de table contiennent parfois eux-mêmes des caractères de soulignement. Cela suit la convention de dénomination des contraintes généralement parce que les noms des éléments de données contiennent souvent des caractères de soulignement, par exemple

CREATE TABLE NaturalPersons (
   ...
   person_death_date DATETIME, 
   person_death_reason VARCHAR(30) 
      CONSTRAINT person_death_reason__not_zero_length
         CHECK (DATALENGTH(person_death_reason) > 0), 
   CONSTRAINT person_death_date__person_death_reason__interaction
      CHECK ((person_death_date IS NULL AND person_death_reason IS NULL)
              OR (person_death_date IS NOT NULL AND person_death_reason IS NOT NULL))
        ...

3
C'est absolument la meilleure réponse.
Frederik Krautwald

1
Je viens de créer Derby DB avec une convention de dénomination très spécifique et celle-ci est la plus lisible et la plus traçable. Merci
Anddo

17

Et pourquoi pas FK_TABLENAME_COLUMNNAME?

K EEP I t S œuvre S tupid chaque fois que possible.


20
Parce que lorsque vous avez une énorme base de données avec beaucoup de clés et de tables et que vous obtenez une erreur lors d'une mise à jour de schéma dans votre logiciel, il est assez difficile de trouver où la clé étrangère est même définie sans effectuer une recherche dans un script de création de base de données.
JohnC

1
@JohnC si les noms de colonne FK ont l'autre nom de table dans le nom de colonne, cela ne devrait-il pas être très facile à dire? Il vous indique les deux tables et le nom de la colonne sur laquelle il est défini. Ex: FK_Animals_OwnerID—Table des animaux et des propriétaires, définie sur la colonne OwnerID
David Sherret

10

Une note de Microsoft concernant SQL Server:

Une contrainte FOREIGN KEY ne doit pas être liée uniquement à une contrainte PRIMARY KEY dans une autre table; il peut également être défini pour référencer les colonnes d'une contrainte UNIQUE dans une autre table.

donc, j'utiliserai des termes décrivant la dépendance au lieu des termes conventionnels de relation primaire / étrangère.

Lors du référencement de la CLÉ PRIMAIRE de la table indépendante (parent) par la ou les colonnes de nom similaire dans la table dépendante (enfant) , j'omets le (s) nom (s) de colonne:

FK_ChildTable_ParentTable

Lors du référencement d'autres colonnes, ou les noms de colonnes varient entre les deux tables, ou simplement pour être explicite:

FK_ChildTable_childColumn_ParentTable_parentColumn

9

Habituellement, je laisse simplement mon ID nommé PK, puis je concatène le nom de ma table et le nom de la colonne clé lors de la dénomination des FK dans d'autres tables. Je ne me soucie jamais de la casse camel, car certaines bases de données ignorent la casse et renvoient simplement tous les noms en majuscules ou minuscules de toute façon. Dans tous les cas, voici à quoi ressemblerait ma version de vos tableaux:

task (id, userid, title);
note (id, taskid, userid, note);
user (id, name);

Notez que je nomme également mes tables au singulier, car une ligne représente l'un des objets que je persiste. Beaucoup de ces conventions sont des préférences personnelles. Je suggérerais qu'il est plus important de choisir une convention et de toujours l'utiliser que d'adopter la convention de quelqu'un d'autre.


heh - c'est le style exact que j'utilise actuellement (mais avec camelCase) - j'ai pensé ajouter un peu de description supplémentaire dans les noms afin d'illustrer leurs liens.
nickf

Donc, au moins, nous pouvons lire les schémas de chacun;) ... ce qui est embarrassant, c'est de ne pas pouvoir lire le vôtre après quelques années d'absence. Nous utilisons ERWin pour schématiser nos schémas, mais il est souvent pratique d'avoir une version texte et d'avoir une convention vous permet de trouver facilement des tables et des champs.
Steve Moyer

5

C'est probablement sur-tuer, mais cela fonctionne pour moi. Cela m'aide beaucoup lorsque je traite en particulier des VLDB. J'utilise ce qui suit:

CONSTRAINT [FK_ChildTableName_ChildColName_ParentTableName_PrimaryKeyColName]

Bien sûr, si pour une raison quelconque vous ne référencez pas une clé primaire, vous devez référencer une colonne contenue dans une contrainte unique, dans ce cas:

CONSTRAINT [FK_ChildTableName_ChildColumnName_ParentTableName_ColumnInUniqueConstaintName]

Cela peut-il être long, oui. Cela a-t-il aidé à garder les informations claires pour les rapports, ou m'a-t-il permis de savoir rapidement que le problème potentiel se produisait lors d'une alerte de production? 100% aimeraient connaître les opinions des gens sur cette convention de dénomination.


1

Mon approche habituelle est

FK_ColumnNameOfForeignKey_TableNameOfReference_ColumnNameOfReference

Ou en d'autres termes

FK_ChildColumnName_ParentTableName_ParentColumnName

De cette façon, je peux nommer deux clés étrangères qui référencent la même table comme une table history_info tablewith column actionBy and actionTofromusers_info

Ce sera comme

FK_actionBy_usersInfo_name - For actionBy
FK_actionTo_usersInfo_name - For actionTo

Notez que:

Je n'ai pas inclus le nom de la table enfant car cela me semble logique, je suis dans la table de l'enfant donc je peux facilement assumer le nom de la table de l'enfant. Le caractère total de celui-ci est de 26 et correspond bien à la limite de 30 caractères d'oracle qui a été déclarée par Charles Burns dans un commentaire ici

Remarque pour les lecteurs: la plupart des bonnes pratiques répertoriées ci-dessous ne fonctionnent pas dans Oracle en raison de sa limite de nom de 30 caractères. Un nom de table ou de colonne peut déjà contenir près de 30 caractères, donc une convention combinant les deux en un seul nom nécessite une norme de troncature ou d'autres astuces. - Charles Burns


Votre un échouera si vous avez la troisième table avec le point FK vers ParentTableName_ParentColumnName même table en dupliquant FK_Name
Tony Dong

0

Sur la base des réponses et des commentaires ici, une convention de dénomination qui inclut la table FK, le champ FK et la table PK (FK_FKTbl_FKCol_PKTbl) devrait éviter les collisions de noms de contraintes FK.

Donc, pour les tableaux donnés ici:

fk_task_userid_user
fk_note_userid_user

Donc, si vous ajoutez une colonne pour suivre la dernière modification d'une tâche ou d'une note ...

fk_task_modifiedby_user
fk_note_modifiedby_user

-2

Si vous ne faites pas souvent référence à vos FK et que vous utilisez MySQL (et InnoDB), vous pouvez simplement laisser MySQL nommer le FK pour vous.

Plus tard, vous pouvez trouver le nom FK dont vous avez besoin en exécutant une requête .


4
Je ne peux qu'expliquer mon vote défavorable. À peu près tous les systèmes de base de données permettent au système de nommer des contraintes, pouvez-vous imaginer revenir en arrière et essayer de comprendre rapidement pendant un problème de production avec même une base de données de 100 tables, en essayant de déchiffrer la relation à laquelle FK__123ee456ff se rapporte? Il est clair et simplement mis une pratique horrible. Quand vous construisez un index sur ce FK alors quoi? les noms de système aussi? Ainsi, lorsque l'index IX_007e373f5963 est fragmenté à 98%, comment saurez-vous où chercher pour comprendre pourquoi? Cela ne devrait tout simplement pas être fait.
SSISPissesMeOff

-3

Essayez d'utiliser l'UUID de la version 4 en majuscules avec le premier octet remplacé par FK et '_' (trait de soulignement) au lieu de '-' (tiret).

Par exemple

  • FK_4VPO_K4S2_A6M1_RQLEYLT1VQYV
  • FK_1786_45A6_A17C_F158C0FB343E
  • FK_45A5_4CFA_84B0_E18906927B53

La justification est la suivante

  • Algorithme de génération strict => noms uniformes ;
  • La longueur de la clé est inférieure à 30 caractères , ce qui est une limitation de longueur de dénomination dans Oracle (avant 12c);
  • Si le nom de votre entité change, vous n'avez pas besoin de renommer votre FK comme dans l'approche basée sur le nom d'entité (si DB prend en charge l'opérateur de changement de nom de table);
  • On utiliserait rarement le nom de la contrainte de clé étrangère. Par exemple, l'outil DB montre généralement à quoi s'applique la contrainte. Pas besoin d'avoir peur du look cryptique, car vous pouvez éviter de l'utiliser pour le "décryptage".
En utilisant notre site, vous reconnaissez avoir lu et compris notre politique liée aux cookies et notre politique de confidentialité.
Licensed under cc by-sa 3.0 with attribution required.