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?
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.
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
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.
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
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.
BOOM, réponse à la question.
Maintenant, dites à votre professeur que SO pratiquez une mauvaise conception de base de données.
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.
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.
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)
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.
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.
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.
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.
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.
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?
Cette question a été battue à plusieurs reprises, mais j'ai pensé que moi aussi j'apporterais mon opinion.
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.
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)
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
id est court et doux aussi
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.
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.
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.