Question

Je me demandais l'opinion des gens sur la dénomination des colonnes d'ID dans les tables de base de données.

Si j'ai une table appelée Factures avec la clé primaire d'une colonne d'identité, j'appellerais cette colonne InvoiceID pour ne pas entrer en conflit avec d'autres tables et il est évident de quoi il s'agit.

Où je suis actuellement au travail, ils ont appelé toutes les colonnes ID.

Ils feraient donc ce qui suit:

Select  
    i.ID 
,   il.ID 
From
    Invoices i
    Left Join InvoiceLines il
        on i.ID = il.InvoiceID

Maintenant, je vois quelques problèmes ici:
1. Vous devez aliaser les colonnes de la sélection

2. ID = InvoiceID ne rentre pas dans mon cerveau
3. Si vous n'avez pas aliasé les tables et fait référence à InvoiceID, la table sur laquelle elle se trouve est-elle évidente?

Quelles sont les opinions des autres peuples sur le sujet?

Était-ce utile?

La solution

ID est un anti-modèle SQL. Voir http: // www.amazon.com/s/ref=nb_sb_ss_i_1_5?url=search-alias%3Dstripbooks&field-keywords=sql+antipatterns&sprefix=sql+a

Si vous avez beaucoup de tables avec ID comme identifiant, vous rendez la tâche de reporting beaucoup plus difficile. Cela obscurcit le sens, rend les requêtes complexes plus difficiles à lire et vous oblige à utiliser des alias pour différencier le rapport lui-même.

En outre, si une personne est assez idiote pour utiliser une jointure naturelle dans une base de données où elle est disponible, vous vous joindrez aux mauvais enregistrements.

Si vous souhaitez utiliser la syntaxe USING autorisée par certaines dbs, vous ne pourrez pas utiliser un identifiant.

Si vous utilisez ID, vous pouvez facilement vous retrouver avec une jointure erronée si vous copiez la syntaxe de la jointure (ne me dites pas que personne ne le fait jamais!) et oubliez de changer l'alias dans la condition de jointure.

Vous avez donc maintenant

select t1.field1, t2.field2, t3.field3
from table1 t1 
join table2 t2 on t1.id = t2.table1id
join table3 t3 on t1.id = t3.table2id

quand vous vouliez dire

select t1.field1, t2.field2, t3.field3 
from table1 t1 
join table2 t2 on t1.id = t2.table1id
join table3 t3 on t2.id = t3.table2id

Si vous utilisez tablenameID comme champ id, ce type d'erreur accidentelle est beaucoup moins susceptible de se produire et beaucoup plus facile à trouver.

Autres conseils

J'ai toujours préféré ID à TableName + ID pour la colonne id, puis TableName + ID pour une clé étrangère. De cette façon, toutes les tables ont le même nom pour le champ id et il n'y a pas de description redondante. Cela me semble plus simple car toutes les tables ont le même nom de champ de clé primaire.

Pour ce qui est de joindre des tables et de ne pas savoir quel champ Id appartient à quelle table, à mon avis, la requête devrait être écrite pour gérer cette situation. Là où je travaille, nous avons toujours préfixé les champs que nous utilisons dans une instruction avec l'alias table / table.

Il y a eu un combat de nerd à propos de cette affaire en ma compagnie ces derniers temps. L’avènement de LINQ a rendu le motif redondant nom_table + ID encore plus évidemment ridicule à mes yeux. Je pense que la plupart des gens raisonnables diront que si vous écrivez manuellement votre code SQL de telle sorte que vous devez spécifier des noms de table pour différencier les FK , il ne s'agit pas uniquement d'une économie de frappe, La clarté de votre code SQL pour utiliser uniquement l'ID car vous pouvez clairement voir quel est le PK et quel est le FK .

ex.

FROM Employees e     JOINDRE GAUCHE clients c ON e.ID = c.EmployeeID

me dit non seulement que les deux sont liés, mais qu'il s'agit du PK et du FK . Tandis que dans le style ancien, on est obligé de regarder ou d’espérer qu’ils portent bien leur nom.

Nous utilisons InvoiceID , et non ID . Cela rend les requêtes plus lisibles - lorsque vous voyez ID seul, cela peut vouloir dire quelque chose, en particulier lorsque vous aliasez la table avec i .

Je suis d'accord avec Keven et quelques autres personnes ici que le PK pour une table devrait simplement être Id et que les clés étrangères listent OtherTable + Id.

Cependant, je souhaite ajouter une raison qui a récemment donné plus de poids à cet argument.

Dans mon poste actuel, nous utilisons le cadre d'entité utilisant la génération POCO. En utilisant la convention de dénomination standard de Id, la PC permet l'héritage d'une classe poco de base avec validation, notamment pour les tables partageant un ensemble de noms de colonnes communs. L'utilisation du nom de table + id en tant que clé de commande pour chacune de ces tables annule la possibilité d'utiliser une classe de base pour celles-ci.

Juste un peu de matière à réflexion.

Ce n'est pas vraiment important, vous rencontrerez probablement des problèmes similaires dans toutes les conventions de nommage.

Mais il est important d'être cohérent pour ne pas avoir à consulter les définitions de table à chaque fois que vous écrivez une requête.

Ma préférence est également ID pour la clé primaire et TableNameID pour la clé étrangère. J'aime aussi avoir une colonne "nom". dans la plupart des tables où je tiens l'identifiant lisible par l'utilisateur (c'est-à-dire :-)) de l'entrée. Cette structure offre une grande flexibilité dans l'application elle-même, je peux manipuler des tables en masse, de la même manière. C’est une chose très très puissante. Un logiciel OO est généralement construit sur la base de données, mais le jeu d'outils OO ne peut pas être appliqué car la base de données elle-même ne le permet pas. Avoir les colonnes id et name n’est toujours pas très bon, mais c’est une étape.

  

Sélectionnez
      i.ID, il.ID à partir de       Factures i       Left Join InvoiceLines il           sur i.ID = il.InvoiceID

Pourquoi ne puis-je pas faire cela?

Select  
    Invoices.ID 
,   InvoiceLines.ID 
From
    Invoices
    Left Join InvoiceLines
        on Invoices.ID = InvoiceLines.InvoiceID

À mon avis, cela est très lisible et simple. Nommer des variables comme i et il est un mauvais choix en général.

Je viens de commencer à travailler dans un endroit qui utilise uniquement "& ID; ID". (dans les tables principales, référencées par TableNameID dans les clés étrangères) et ont déjà détecté DEUX problèmes de production directement causés par celui-ci.

Dans un cas, la requête a utilisé "... où ID dans (SELECT ID DE FROM OtherTable ..." au lieu de "... où ID dans (SELECT TransID FROM OtherTable ...".

Est-ce que quelqu'un peut honnêtement dire que cela n'aurait pas été beaucoup plus facile à repérer si des noms complets et cohérents étaient utilisés là où l'énoncé erroné aurait été lu "... où TransID dans (SELECT OtherTableID from OtherTable ..." Je ne pense pas.

L'autre problème se produit lors du refactoring du code. Si vous utilisez une table temporaire alors que précédemment, la requête contenait une table principale, l'ancien code était libellé comme suit: "... dbo.MyFunction (t.ID) ...". et si cela ne change pas mais "t"; fait maintenant référence à une table temporaire au lieu de la table principale, vous n’obtenez même pas une erreur, mais des résultats erronés.

Si la création d’erreurs inutiles est un objectif (certaines personnes n’ont peut-être pas assez de travail?), ce type de convention de nommage est excellent. Sinon, un nom cohérent est la voie à suivre.

Par souci de simplicité, la plupart des gens nomment la colonne sur l'ID de la table. S'il y a une référence de clé étrangère sur une autre table, alors ils l'appellent explicitement InvoiceID (pour utiliser votre exemple) dans le cas de jointures, vous aliasez toujours la table de sorte que l'identifiant explicatif inv.ID est toujours plus simple que inv.InvoiceID

Pour en venir à cela du point de vue d’un dictionnaire de données formel, j’appellerais l’élément de données invoice_ID . En règle générale, un nom d'élément de données sera unique dans le dictionnaire de données et, idéalement, portera toujours le même nom, bien que des termes qualificatifs supplémentaires puissent parfois être requis en fonction du contexte, par exemple. L'élément de données nommé ID_employé peut être utilisé deux fois dans l'organigramme et donc qualifié de supervisor_Employé et de subordinate_employee_ID respectivement.

Évidemment, les conventions de dénomination sont subjectives et une question de style. Les lignes directrices ISO / CEI 11179 constituent un bon point de départ.

Pour le SGBD, je considère les tables comme des ensembles d'entités (à l'exception de celles ne contenant qu'une seule ligne, par exemple, une table cofig, une table de constantes, etc.), par exemple. la table où mon ID_employé est la clé s'appelle Personnel . Alors tout de suite, la convention TableNameID ne fonctionne pas pour moi.

J'ai vu le style TableName.ID = PK TableNameID = FK utilisé sur des modèles de données volumineux et je dois dire que je le trouve un peu déroutant: je préfère de loin le nom d'un identifiant identique. ne change pas de nom en fonction de la table dans laquelle il apparaît. Le style susmentionné semble être utilisé dans les magasins qui ajoutent une colonne IDENTITY (incrémentation automatique) à chaque en évitant les clés naturelles et composées dans les clés étrangères. Ces magasins n’ont généralement pas de dictionnaires de données officiels ni de modèles de données. Encore une fois, il s’agit simplement d’une question de style à laquelle je ne souscris pas personnellement. Donc, finalement, ce n'est pas pour moi.

Cela étant dit, je peux parfois constater que le qualificatif est supprimé du nom de la colonne lorsque le nom de la table fournit un contexte permettant de le faire, par exemple. L'élément nommé nom_employé peut devenir simplement nom dernier dans la table Personnel . La raison ici est que le domaine est "les noms des personnes" et est plus susceptible d'être UNION ed avec dernier nom colonnes à partir de autres tables plutôt que être utilisé comme clé étrangère dans une autre table, mais encore une fois ... je pourrais changer d'avis, parfois, vous ne pouvez jamais le savoir. C’est ça: la modélisation des données est à la fois un art et une science.

Je personnellement préfère (comme il a été dit plus haut) les Table.ID pour les PK et les TableID pour le FK . Même (ne me tirez pas dessus s'il vous plaît), Microsoft Access le recommande.

TOUJOURS, je sais aussi que certains outils de génération favorisent le TableID pour PK car ils ont tendance à lier tous les noms de colonnes contenant 'ID' dans le mot, INCLUDING ID! !!

Même le concepteur de requêtes le fait sur Microsoft SQL Server (et pour chaque requête que vous créez, vous finissez par extraire toutes les relations inutiles nouvellement créées sur toutes les tables sur l'ID de la colonne)

DONC, autant que mon OCD interne le déteste, je respecte la convention TableID . Rappelons-nous qu’il s’appelle Data BASE , car ce sera la base pour de nombreuses applications à venir. Et toutes les technologies devraient bénéficier d’un schéma bien décrit avec une description claire.

Il va sans dire que je dessine ma ligne quand les gens commencent à utiliser TableName, TableDescription et autres. À mon avis, les conventions devraient procéder comme suit:

  • Nom de la table: Pluralized. Ex. Employés
  • Alias ??de table: Nom complet de la table, singularisé. Ex.

    SELECT Employee.*, eMail.Address
    FROM Employees AS Employee LEFT JOIN eMails as eMail on Employee.eMailID = eMail.eMailID -- I would sure like it to just have the eMail.ID here.... but oh well
    

[Mise à jour]

De plus, certaines discussions valides de ce fil traitent des colonnes dupliquées en raison du "type de relation". ou rôle. Exemple, si un magasin a un ID d'employé , cela m'indique squat. Je fais donc parfois quelque chose comme Store.EmployeeID_Manager . Bien sûr, il est un peu plus grand, mais au moins, les gens ne vont pas devenir fous à la recherche de table ManagerID ou de ce que EmployeeID y fait. Quand interroger est O je voudrais le simplifier en tant que:     SELECT EmployeeID_Manager en tant que ManagerID FROM Store

Je pense que vous pouvez utiliser n'importe quoi pour l'identifiant "ID". tant que vous êtes cohérent. Inclure le nom de la table est important pour. Je suggérerais d'utiliser un outil de modélisation comme Erwin pour appliquer les conventions et normes de dénomination. Ainsi, lors de l'écriture de requêtes, il est facile de comprendre les relations qui peuvent exister entre les tables.

Ce que je veux dire par la première déclaration est qu’au lieu d’identifiant, vous pouvez utiliser quelque chose comme "recno". Donc, alors cette table aurait un PK de invoice_recno et ainsi de suite.

Salut, Ben

Mon vote est pour InvoiceID pour l'ID de table. J'utilise également la même convention d'appellation lorsqu'elle est utilisée comme clé étrangère et que des noms d'alias intelligents sont utilisés dans les requêtes.

 Select Invoice.InvoiceID, Lines.InvoiceLine, Customer.OrgName
 From Invoices Invoice
 Join InvoiceLines Lines on Lines.InvoiceID = Invoice.InvoiceID
 Join Customers Customer on Customer.CustomerID = Invoice.CustomerID

Bien sûr, il est plus long que d’autres exemples. Mais souriez. C'est pour la postérité et un jour, un pauvre codeur junior va devoir modifier votre chef-d'œuvre. Dans cet exemple, il n'y a aucune ambiguïté et au fur et à mesure que des tables supplémentaires sont ajoutées à la requête, vous serez reconnaissant pour la verbosité.

Pour le nom de la colonne dans la base de données, j'utiliserais "InvoiceID".

Si je copie les champs dans une structure non nommée via LINQ, je peux le nommer "ID". là, si c’est le seul identifiant dans la structure.

Si la colonne ne doit PAS être utilisée dans une clé étrangère, de sorte qu'elle soit uniquement utilisée pour identifier de manière unique une ligne à modifier ou à supprimer, je la nommerai "PK".

Si vous attribuez un nom unique à chaque clé, par exemple " invoices.invoice_id " au lieu de "invoices.id", vous pouvez utiliser la "jointure naturelle". et " utiliser " opérateurs sans soucis. Ex.

SELECT * FROM invoices NATURAL JOIN invoice_lines
SELECT * FROM invoices JOIN invoice_lines USING (invoice_id)

au lieu de

SELECT * from invoices JOIN invoice_lines
    ON invoices.id = invoice_lines.invoice_id

SQL est suffisamment détaillé sans le rendre plus détaillé.

Ce que je fais pour garder les choses cohérentes pour moi (lorsqu'une table a une clé primaire à une seule colonne utilisée comme ID) est de nommer la clé primaire de la table Table_pk . Partout où j'ai une clé étrangère qui pointe vers la clé primaire de cette table, j'appelle la colonne PrimaryKeyTable_fk . Ainsi, je sais que si j'ai un Customer_pk dans ma table Client et un Customer_fk dans ma table Order, je sais que la table Order fait référence à une entrée dans Customer. table.

Pour moi, cela est particulièrement utile pour les jointures où je pense que cela se lit plus facilement.

SELECT * 
FROM Customer AS c
    INNER JOIN Order AS c ON c.Customer_pk = o.Customer_fk

FWIW, notre nouvelle norme (qui change, euh, je veux dire "évolue", à chaque nouveau projet) est la suivante:

  • Noms de champs de la base de données en minuscules
  • Noms de table en majuscule
  • Utilisez des traits de soulignement pour séparer les mots dans le nom du champ - convertissez-les en casse Pascal dans le code.
  • pk _ le préfixe signifie clé primaire
  • Le suffixe
  • _id désigne un entier, un identifiant à incrémentation automatique
  • fk _ le préfixe signifie une clé étrangère (aucun suffixe n'est nécessaire)
  • _VW suffixe pour les vues
  • est le préfixe _ pour les booléens

Ainsi, une table nommée NAMES peut contenir les champs nom_pk, id_nom, dernier nom, is_alive, et fk_company et une vue appelée LIVING_CUSTOMERS_VW , défini comme:

SELECT first_name, last_name
FROM CONTACT.NAMES
WHERE (is_alive = 'True')

Comme d'autres l'ont déjà dit, à peu près n'importe quel schéma fonctionnera tant qu'il sera cohérent et ne dissimulera pas inutilement votre sens.

Je suis tout à fait d’accord pour inclure le nom de la table dans le nom du champ ID, pour les raisons que vous donnez. Généralement, c’est le seul champ dans lequel j’inclue le nom de la table.

Je déteste le nom d'identité en clair. Je préfère fortement utiliser toujours facture_id ou une variante de celui-ci. Je sais toujours quelle table est la table faisant autorité pour l'id lorsque j'en ai besoin, mais cela me perturbe

SELECT * from Invoice inv, InvoiceLine inv_l where 
inv_l.InvoiceID = inv.ID 
SELECT * from Invoice inv, InvoiceLine inv_l where 
inv_l.ID = inv.InvoiceLineID 
SELECT * from Invoice inv, InvoiceLine inv_l where 
inv_l.ID = inv.InvoiceID 
SELECT * from Invoice inv, InvoiceLine inv_l where 
inv_l.InvoiceLineID = inv.ID 

Le pire de tous est le mélange que vous mentionnez, totalement déroutant. J'ai dû travailler avec une base de données où il s'agissait presque toujours de foo_id sauf dans l'un des identifiants les plus utilisés. C'était un enfer total.

Je préfère DomainName || 'ID'. (c'est-à-dire nom de domaine + ID)

DomainName est souvent, mais pas toujours, identique à TableName.

Le problème avec l’ID en lui-même est qu’il ne monte pas en puissance. Une fois que vous avez environ 200 tables, chacune avec une première colonne nommée ID, les données commencent à se ressembler. Si vous qualifiez toujours ID avec le nom de la table, cela aide un peu, mais pas tant que ça.

DomainName & amp; ID peut être utilisé pour nommer des clés étrangères ainsi que des clés primaires. Lorsque les clés foriegn sont nommées d'après la colonne qu'elles référencent, cela peut être d'une aide mnémonique. Formellement, lier le nom d'une clé étrangère à la clé qu'elle référence n'est pas nécessaire, car la contrainte d'intégrité référentielle établira la référence. Mais c’est terriblement pratique pour lire les requêtes et les mises à jour.

Occasionnellement, DomainName || 'ID' ne peut pas être utilisé car il y aurait deux colonnes dans le même tableau avec le même nom. Exemple: Employees.EmployeeID et Employees.SupervisorID. Dans ces cas, j'utilise RoleName || "ID", comme dans l'exemple.

Enfin, j'utilise des clés naturelles plutôt que des clés synthétiques lorsque cela est possible. Il existe des situations où les clés naturelles sont indisponibles ou indignes de confiance, mais il existe de nombreuses situations dans lesquelles la clé naturelle est le bon choix. Dans ces cas, je laisse la clé naturelle prendre le nom qu'il aurait naturellement. Ce nom n’a souvent même pas les lettres «ID». Exemple: OrderNo où No est l'abréviation de "Number".

Pour chaque tableau, je choisis un raccourci d'arbre (par exemple, Employees = > Emp)

.

Ainsi, une clé primaire numérotée automatiquement devient nkEmp .

Il est court, unique dans toute la base de données et je connais exactement ses propriétés en un coup d’œil.

Je conserve les mêmes noms dans SQL et dans tous les langages que j'utilise (principalement C #, Javascript, VB6).

Voir le site Web d'Interakt conventions de dénomination pour un système bien pensé de dénomination de tables et de colonnes. La méthode utilise un suffixe pour chaque table ( _prd pour une table produit ou _ctg pour une table catégorie) et l'ajoute à chaque colonne d'une table donnée. La colonne d'identité de la table products serait donc id_prd et est donc unique dans la base de données.

Ils vont un peu plus loin pour aider à comprendre les clés étrangères: la clé étrangère dans la table product qui fait référence à la table des catégories serait idctg_prd , de sorte qu'il soit facile d'identifier la table à laquelle elle appartient ( _prd suffixe) et à quelle table il fait référence (catégorie).

Les avantages sont qu’il n’ya aucune ambiguïté dans les colonnes d’identité des différentes tables et que vous pouvez savoir en un coup d’œil à quelles colonnes une requête se réfère par leur nom.

Vous pouvez utiliser la convention de dénomination suivante. Il a ses défauts mais il résout vos problèmes particuliers.

  1. Utilisez des pseudonymes courts (3 à 4 caractères) pour les noms de table, par exemple Facture - inv , FacturesLines - invl
  2. Nommez les colonnes de la table en utilisant ces surnoms, à savoir inv_id , invl_id
  3. Pour les colonnes de référence, utilisez invl_inv_id pour les noms.

De cette façon, vous pourriez dire

SELECT * FROM Invoice LEFT JOIN InvoiceLines ON inv_id = invl_inv_id
Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top