web-dev-qa-db-fra.com

Pourquoi le fait de nommer la colonne de clé primaire d'une table "Id" est-il considéré comme une mauvaise pratique?

Mon professeur de t-sql nous a dit que nommer notre colonne PK "Id" est considéré comme une mauvaise pratique sans autre explication.

Pourquoi nommer une colonne PK de table "Id" est-il considéré comme une mauvaise pratique?

215

Je vais sortir et le dire: ce n'est pas vraiment une mauvaise pratique (et même si c'est le cas, ce n'est pas que mauvais).

Vous pourriez faire valoir (comme Chad l'a souligné) qu'il peut masquer des erreurs comme dans la requête suivante:

SELECT * 
    FROM cars car
    JOIN manufacturer mfg
        ON mfg.Id = car.ManufacturerId
    JOIN models mod
        ON mod.Id = car.ModelId
    JOIN colors col
        ON mfg.Id = car.ColorId

mais cela peut facilement être atténué en n'utilisant pas de minuscules alias pour les noms de vos tables:

SELECT * 
    FROM cars
    JOIN manufacturer
        ON manufacturer.Id = cars.ManufacturerId
    JOIN models
        ON models.Id = cars.ModelId
    JOIN colors
        ON manufacturer.Id = cars.ColorId

La pratique de TOUJOURS utiliser des abréviations de 3 lettres me semble bien pire que d'utiliser le nom de colonne id. (Exemple: qui abrégerait réellement le nom de la table cars avec l'abréviation car? À quelle fin cela sert-il?)

Le point est: soyez cohérent. Si votre entreprise utilise l'ID et que vous commettez généralement l'erreur ci-dessus, prenez l'habitude d'utiliser des noms de table complets. Si votre entreprise interdit la colonne Id, prenez-la à votre rythme et utilisez la convention de dénomination qu'elle préfère.

Concentrez-vous sur l'apprentissage de choses qui sont réellement de mauvaises pratiques (telles que plusieurs sous-requêtes corrélées imbriquées) plutôt que de réfléchir à des problèmes comme celui-ci. La question de nommer vos colonnes "ID" est plus proche d'une question de goût que d'une mauvaise pratique.


NOTE AUX RÉDACTEURS EN CHEF: L'erreur dans cette requête est intentionnelle et est utilisée pour faire un point. Veuillez lire la réponse complète avant de modifier.

250
riwalk

Parce que lorsque vous avez une table avec une clé étrangère, vous ne pouvez pas nommer cette clé étrangère "Id". Vous avez le nom de table TableId

Et puis votre jointure ressemble

SELECT * FROM cars c JOIN manufacturer m ON m.Id = c.ManufacturerId

Et idéalement, votre condition devrait avoir le même nom de champ de chaque côté

SELECT * FROM cars c JOIN manufacturer m ON m.ManufacturerId = c.ManufacturerId

Ainsi, même s'il semble redondant de nommer l'ID en tant que ManufacturerId, il est moins probable que vous ayez des erreurs dans vos conditions de jointure, car les erreurs deviennent évidentes.

Cela semble simple, mais lorsque vous rejoignez plusieurs tables, il est plus probable que vous fassiez une erreur, trouvez celle ci-dessous ...

SELECT * 
    FROM cars car 
    JOIN manufacturer mfg
        ON mfg.Id = car.ManufacturerId
    JOIN models mod
        ON mod.Id = car.ModelId
    JOIN colors col
        ON mfg.Id = car.ColorId

Alors qu'avec un nom correct, l'erreur persiste ...

SELECT * 
    FROM cars car 
    JOIN manufacturer mfg
        ON mfg.ManufacturerId = car.ManufacturerId
    JOIN models mod
        ON mod.ModelId = car.ModelId
    JOIN colors col
        ON mfg.ManufacturerId = car.ColorId

Une autre raison pour laquelle leur nom est "mauvais" est que lorsque vous recherchez des informations à partir de plusieurs tables, vous devrez renommer les colonnes Id afin de pouvoir les distinguer.

SELECT   manufacturer.Id as 'ManufacturerId'
        ,cars.Id as 'CarId'
        --etc
    FROM cars 
    JOIN manufacturer
        ON manufacturer.Id = cars.Id

Avec des noms précis, c'est moins un problème

125
CaffGeek

La bibliothèque ActiveRecord de Ruby et GORM de Groovy utilisent par défaut "id" pour la clé de substitution. J'aime cette pratique. La duplication du nom de table dans chaque nom de colonne est redondante, fastidieuse à écrire et plus fastidieuse à lire.

68
kevin cline

Les noms de colonne communs ou clés tels que "Nom" ou "Id" doivent être précédés du nom de table.

Il supprime l'ambiguïté, plus facile à rechercher, signifie beaucoup moins d'alias de colonne lorsque les deux valeurs "Id" sont nécessaires.

Une colonne moins utilisée ou d'audit ou une non-clé (par exemple LastUpdatedDateTime) n'a pas d'importance

40
gbn

Ce fil est mort, mais je voudrais ajouter que IMO pas en utilisant Id est une mauvaise pratique. La colonne Id est spéciale; c'est la clé primaire. Toute table peut avoir n'importe quel nombre de clés étrangères, mais elle ne peut avoir qu'une seule clé principale. Dans une base de données où toutes les clés primaires sont appelées Id, dès que vous regardez la table, vous savez exactement quelle colonne est la clé primaire.

Croyez-moi, depuis des mois, je passe toute la journée à travailler dans de nombreuses grandes bases de données (Salesforce) et la meilleure chose que je puisse dire sur les schémas est que chaque table a une clé primaire appelée Id. Je peux vous assurer que je ne me trompe jamais de joindre une clé primaire à une clé étrangère parce que le PK est appelé Id. Une autre chose que les gens n'ont pas mentionnée est que les tables peuvent avoir de longs noms idiots comme Table_ThatDoesGood_stuff__c; ce nom est déjà assez mauvais parce que l'architecte a eu une gueule de bois le matin où il a inventé cette table, mais maintenant vous me dites que c'est une mauvaise pratique de ne pas appeler la clé primaire Table_ThatDoesGood_stuff__cId (en se souvenant que les noms de colonnes SQL ne sont généralement pas sensibles à la casse).

Pour être honnête, les problèmes avec la plupart des gens qui enseignent la programmation informatique sont qu'ils n'ont pas écrit de ligne de code de production depuis des années, voire jamais, et ils n'ont aucune idée de ce que fait réellement un ingénieur logiciel en activité. Attendez de commencer à travailler, puis décidez ce que vous pensez être une bonne idée ou non.

32
user23157

De data.stackexchange.com

Id in Posts

BOOM, réponse à la question.
Maintenant, dites à votre professeur que SO pratiquez une mauvaise conception de base de données.

25
Cyril Gandon

Je ne considère pas cela comme une mauvaise pratique. La cohérence est roi, comme d'habitude.

Je pense que c'est une question de contexte. Dans le contexte du tableau à lui seul, "id" signifie exactement ce que vous attendez, une étiquette pour aider à l'identifier de manière unique par rapport à d'autres qui pourraient autrement être (ou apparaître) identiques.

Dans le contexte des jointures, il est de votre responsabilité de construire les jointures de manière à les rendre lisibles pour vous et votre équipe. Tout comme il est possible de rendre les choses difficiles avec un mauvais phrasé ou un mauvais nommage, il est également possible de construire une requête significative avec une utilisation efficace des alias et même des commentaires.

De la même manière, une classe Java classe appelée 'Foo' n'a pas ses propriétés préfixées par 'Foo', ne vous sentez pas obligé de préfixer vos ID de table avec les noms de table. Il est généralement clair en contexte quel est l'ID auquel il est fait référence.

24
lotsoffreetime

Il est difficile (et déroutant) d'effectuer une jointure naturelle sur la table, donc oui, c'est mauvais sinon très mauvais.

La jointure naturelle est un ancien artefact de la tradition SQL (c'est-à-dire l'algèbre relationnelle), vous en avez peut-être vu une: ⋈ dans un livre de base de données peut-être. Ce que je veux dire, c'est que Natrual Join n'est pas une nouvelle idée SQL fangled, même si cela semblait prendre une éternité pour que les SGBD l'aient implémenté, donc ce n'est pas une nouvelle idée fangled pour vous de l'implémenter, il pourrait même être déraisonnable pour vous d'ignorer son existence de nos jours.

Eh bien, si vous nommez tous les ID de votre clé primaire, vous perdez la facilité et la simplicité de la jointure naturelle. select * from dudes natural join cars devra être écrit select * from dudes inner join cars where cars.dudeid = dudes.id ou select * from dudes inner join cars where dudes.carid = cars.id. Si vous êtes capable de faire une jointure naturelle, vous pouvez ignorer ce qu'est réellement la relation, ce qui, je crois, est assez impressionnant.

17
Peter Turner

Il y a une situation où coller "ID" sur chaque table n'est pas la meilleure idée: le mot clé USING, s'il est pris en charge. Nous l'utilisons souvent dans MySQL.

Par exemple, si vous avez fooTable avec la colonne fooTableId et barTable avec la clé étrangère fooTableId, alors vos requêtes peuvent être construites comme telles:

SELECT fooTableId, fooField1, barField2 FROM fooTable INNER JOIN barTable USING (fooTableId)

Il enregistre non seulement la saisie, mais est beaucoup plus lisible par rapport à l'alternative:

SELECT fooTable.Id, fooField1, barField2 FROM fooTable INNER JOIN barTable ON (fooTable.Id = barTable.foTableId)
16
Izkata

Pourquoi ne pas simplement demander à votre professeur?

Pensez-y, lorsque toutes vos colonnes PK de tables sont nommées ID cela fait de leur utilisation comme clés étrangères un cauchemar.

Les noms de colonne doivent être sémantiquement significatifs. ID est générique.

11
user7519

L'ID est mauvais pour les raisons suivantes:

Si vous effectuez de nombreuses requêtes de génération de rapports, vous devez toujours alias les colonnes si vous voulez voir les deux. Donc, cela devient une perte de temps lorsque vous pouvez le nommer correctement pour commencer. Ces requêtes complexes sont assez difficiles (j'écris des requêtes qui peuvent être des centaines de lignes) sans la charge supplémentaire de faire un travail inutile.

Il est susceptible de provoquer des erreurs de code. Si vous utilisez une base de données qui permet l'utilisation de la jointure naturelle (pas que je pense que vous devriez jamais l'utiliser, mais lorsque des fonctionnalités sont disponibles, quelqu'un les utilisera), vous vous joindrez à la mauvaise chose si vous obtenez un développeur qui l'utilise.

Si vous copiez des jointures pour créer une requête complexe, il est facile d'oublier de remplacer l'alias par celui que vous souhaitez et d'obtenir une jointure incorrecte. Si chaque identifiant est nommé d'après la table dans laquelle il se trouve, vous obtiendrez généralement une erreur de syntaxe. Il est également plus facile de repérer si la jointure dans une requête complexe est incorrecte si le nom pPK et le nom FK correspondent.

7
HLGEM

La pratique consistant à utiliser Id comme champ de clé primaire conduit à la pratique dans laquelle id est ajouté à chaque table. De nombreuses tables contiennent déjà des informations uniques qui identifient de manière unique un enregistrement. Utilisez CELA comme clé primaire et non un champ id que vous ajoutez à chaque table. C'est l'un des fondements des bases de données relationnelles.

Et c'est pourquoi utiliser id est une mauvaise pratique: id n'est souvent pas une simple augmentation automatique de l'information.

considérez les tableaux suivants:

PK id | Countryid   | Countryname
    1 |         840 | United States
    2 |         528 | the Netherlands

Ce qui ne va pas avec ce tableau, c'est qu'il permet à l'utilisateur d'ajouter une autre ligne: États-Unis, avec le code de pays 840. Il vient de briser l'intégrité relationnelle. Bien sûr, vous pouvez appliquer l'unicité sur des colonnes individuelles, ou vous pouvez simplement utiliser une clé primaire qui est déjà disponible:

PK Countryid   | Countryname
           840 | United States
           528 | the Netherlands

De cette façon, vous utilisez les informations que vous avez déjà comme clé primaire, qui est au cœur de la conception de la base de données relationnelle.

5
Pieter B

Il y a quelques réponses qui s'approchent de ce que je considérerais comme la raison la plus importante pour ne pas utiliser "id" comme nom de colonne pour la clé primaire dans une table: à savoir la cohérence et l'ambiguïté réduite.

Cependant, pour moi, le principal avantage est réalisé par le programmeur de maintenance, en particulier celui qui n'était pas impliqué dans le développement d'origine. Si vous avez utilisé le nom "PersonID" pour l'ID dans la table Person et que vous l'avez toujours utilisé comme clé étrangère, il est trivial d'écrire une requête sur le schéma pour savoir quelles tables ont PersonID sans avoir à déduire ce "PersonID" est le nom utilisé lorsqu'il s'agit d'une clé étrangère. N'oubliez pas, à tort ou à raison, que les relations avec les clés étrangères ne sont pas toujours appliquées dans tous les projets.

Il y a un cas Edge où une table peut avoir besoin d'avoir deux clés étrangères à la même table, mais dans de tels cas, je mettrais le nom de clé d'origine comme nom de suffixe pour la colonne, donc une correspondance générique,% PersonID, pourrait facilement trouver ces cas aussi.

Oui, une grande partie de cela pourrait être accomplie par une norme ayant "id" et sachant de toujours l'utiliser comme "tableNameID", mais cela nécessite à la fois de savoir que la pratique est en place et de dépendre des développeurs originaux pour suivre avec moins pratique standard intuitive.

Alors que certaines personnes ont souligné qu'il fallait des touches supplémentaires pour écrire les noms de colonnes plus longs, je suppose que l'écriture du code n'est qu'une petite fraction de la vie active du programme. Si l'objectif était de sauvegarder les frappes des développeurs, les commentaires ne devraient jamais être écrits.

En tant que personne qui a passé de nombreuses années à gérer de grands projets avec des centaines de tables, je préférerais fortement des noms cohérents pour une clé entre les tables.

5
Malachi

J'utilise toujours 'id' comme nom de colonne primaire pour chaque table simplement parce que c'est la convention des frameworks que j'utilise (Ruby on Rails, CakePHP), donc je n'ai pas à le remplacer tout le temps.

Cela ne battra pas les raisons académiques pour moi.

4
Sfynx

L'identification est assez courante, pour que je ne pense pas que cela dérouterait qui que ce soit. Vous voudrez toujours connaître la table. Mettre des noms de champs dans le code de production sans inclure de table/alias est une mauvaise pratique. Si vous êtes trop préoccupé par la possibilité de taper rapidement des requêtes ad hoc, vous êtes seul.

Espérons juste que personne ne développe une base de données SQL où ID est un mot réservé.

CREATE TABLE CAR (ID);

Prend soin du nom du champ, de la clé primaire et des incréments automatiques de 1 en commençant par 1 tout en un joli petit paquet de 2 caractères. Oh, et je l'aurais appelé CARS, mais si nous allons économiser sur les touches et qui pense vraiment qu'une table appelée CAR n'en aura qu'un?

2
JeffO

Cette question a été battue à plusieurs reprises, mais j'ai pensé que moi aussi j'apporterais mon opinion.

  1. J'utilise id pour signifier qu'il s'agit de l'identifiant de chaque table, donc lorsque je me joins à une table et que j'ai besoin de la clé primaire, je me joins automatiquement à la clé primaire.

  2. Le champ id est un auto-incrément, non signé (ce qui signifie que je n'ai jamais à définir sa valeur et qu'il ne peut pas être négatif)

  3. Pour les clés étrangères, j'utilise tablenameid (encore une fois une question de style), mais la clé primaire à laquelle je me joins est le champ id de la table, donc la cohérence signifie que je peux toujours vérifier les requêtes facilement

  4. id est court et doux aussi

  5. Convention supplémentaire - utilisez des minuscules pour tous les noms de table et de colonne, donc aucun problème à trouver en raison de la casse

Je ne pense pas que ce soit une mauvaise pratique s'il est utilisé correctement. Il est courant d'avoir un champ d'ID à incrémentation automatique appelé "ID" que vous n'avez jamais à toucher, et d'utiliser un identifiant plus convivial pour l'application. Cela peut être un peu lourd d'écrire du code comme from tableA a inner join tableB b on a.id = b.a_id mais ce code peut être caché.

En tant que préférence personnelle, j'ai tendance à préfixer l'ID avec le nom de l'entité, mais je ne vois pas de problème réel avec simplement l'utilisation de Id si elle est entièrement gérée par la base de données.

2
Wayne Molina

Je trouve que les gens couvrent à peu près tous les aspects, mais je tiens à ajouter que "id" n'est pas et ne doit pas être lu comme "identificateur", il s'agit plutôt d'un "index" et qu'il n'énonce ni ne décrit sûrement l'identité de la ligne. (J'ai peut-être utilisé une mauvaise formulation ici, veuillez me corriger si je l'ai fait)

C'est plus ou moins comment les gens lisent les données de la table et comment ils écrivent leur code. Personnellement, c'est probablement la façon la plus populaire que je vois le plus fréquemment: les codeurs écrivent la référence complète comme table.id, même s'ils n'ont pas besoin de faire l'union et/ou les jointures. Par exemple:

SELECT cars.color, cars.model FROM cars WHERE cars.id = <some_var>

De cette façon, vous pouvez le traduire en anglais comme "Donnez-moi la couleur et le modèle de cette voiture qui est numérotée comme." et non pas comme "Donnez-moi la couleur et le modèle de cette voiture qui est identifiée comme un numéro." L'ID ne représente en aucune façon la voiture, c'est seulement l'index de la voiture, un numéro de série si vous voulez. Tout comme lorsque vous souhaitez extraire le troisième élément d'un tableau.

Donc, pour résumer ce que je voulais ajouter, c'est que c'est juste une question de préférence et la manière décrite de lire SQL est la plus populaire.

Cependant, il y a des cas où cela n'est pas utilisé, comme (un exemple beaucoup plus rare) lorsque l'ID est une chaîne qui décrit vraiment. Par exemple id = "RedFordMustang1970" ou quelque chose de similaire. J'espère vraiment que je pourrais l'expliquer au moins pour avoir l'idée.

1
Sergey Telshevsky

Une autre chose à considérer est que si le nom de la clé primaire est différent du nom de la clé étrangère, il n'est pas possible d'utiliser certains outils tiers.

Par exemple, vous ne pourriez pas charger votre schéma dans un outil comme Visio et lui faire produire des ERD précis.

1
1earldog