Quel est un moyen efficace d'étiqueter des colonnes dans une base de données?

30

J'avais l'habitude d'étiqueter des colonnes dans mes bases de données comme ceci:

user_id
user_name
user_password_hash

Pour éviter les conflits lors de la jonction de deux tables, mais j'ai appris un peu plus sur l'alias des tables et j'ai arrêté de le faire.

Quel est un moyen efficace d'étiqueter des colonnes dans une base de données? Pourquoi?

Thomas O
la source
Quelle base de données? La façon dont j'étiquette dans Oracle est différente de la plupart des autres bases de données en raison de sa fonction de sélection automatique des colonnes sur lesquelles baser les jointures si les noms correspondent.
Joe
@Joe, Eh bien, j'ai toujours utilisé MySQL et SQLite3, mais cela devrait s'appliquer à la plupart des autres bases de données.
Thomas O
@joe n'a jamais remarqué qu'Oracle est différent. Pouvez-vous donner un lien?
bernd_k
@bernd_k: J'ai ajouté quelques liens à ma réponse ci
Joe

Réponses:

33

Dans votre cas, l'utilisateur du préfixe est redondant. Nous (les développeurs responsables) savons que c'est l'utilisateur de la table, alors pourquoi ajouter un user_préfixe devant chaque champ?

Ce que je vous suggère, c'est de le faire avec une approche plus naturelle.

Quelles sont les caractéristiques d'une personne: nom, prénom, date de naissance, nationalité, etc ...

Quelles sont les caractéristiques d'une voiture: modèle, année, couleur, énergie, etc ...

Votre colonne devrait être nommée aussi naturelle que possible, cela rendrait le schéma plus clair pour tout le monde, pour vous et pour ceux qui vous suivent. Cela s'appelle également la phase de maintenance, et tout ce que vous pouvez faire pour faciliter la maintenance en vaut la peine.

Spredzy
la source
1
Oui, ça me rend furieux quand les gens font ça. Aussi quand ils appellent toute leur table tbl_wimporte.
Gaius
Ceci est également pertinent pour le concept de «mots de classe», et il semble y avoir un débat dans la communauté lorsque les mots de classe sont et ne sont pas appropriés. (un mot de classe est un outil pour: identifier une catégorie distincte ou une classification des données, délimiter le type de données décrit par le nom des données et décrire la classification principale des données associées à un élément de données.)
Jon Schoning
17

En plus du commentaire de Spredzy, étiquetez vos clés primaires de la même manière (ID) de sorte que lorsque vous écrivez des requêtes à la volée, vous pouvez facilement rappeler (u.ID = c.ID) au lieu d'avoir à rechercher "Était-ce countryID , country_ID, countries_ID, countriesID,? "

David Hall
la source
5
Une fois, j'ai travaillé sur une base de données où le DBA a décidé d'utiliser ID dans certaines tables et id dans d'autres et nous avons configuré MySQL pour qu'il soit sensible à la casse ... des moments amusants!
Toby
6
Nous utilisons généralement tablename.tablename_id. Par exemple, car.car_id; person.person_id. Noms singuliers pour les tables.
glasnt le
@glasnt décision intelligente.
garik
1
C'est en fait une très mauvaise idée, et vous perdrez la possibilité d'utiliser la USINGclause SQL (c'est contre la spécification).
Evan Carroll
9

Je ne pourrais être plus d'accord avec l'addendum de David Hall à l'excellente réponse de Spredzy. La voie à suivre est simple et naturelle. La confusion des tables ne devrait pas être un problème si vous nommez aussi naturellement les tables.

Cela n'a aucun sens d'avoir users.user_id et cars.car_id quand vous pourriez avoir users.id et cars.id

bsoist
la source
7

Je dirais que dans un schéma de base de données, chaque colonne doit avoir un nom unique, à travers les tables. Il y a plusieurs raisons à cela:

  • Du point de vue de la modélisation: vous commencez avec une soupe d'attributs et vous la normalisez en tableaux. Au fil du temps, vous pouvez dénormaliser ou normaliser davantage ou introduire des vues ou des vues matérialisées, ou introduire de nouvelles tables. Ce n'est jamais un problème si tous les noms de colonnes sont uniques.

  • Vous pouvez utiliser cette syntaxe de jointure: a JOIN b USING (a_id) JOIN c USING (a_id). Très pratique et aide également au point suivant.

  • Si vous exécutez des requêtes avec de nombreuses jointures ou créez des vues matérialisées avec SELECT *, vous n'aurez jamais (enfin, peut-être rarement) un conflit. Pensez à joindre person.name, product.name, country.name, etc. Urgh.

  • En général, si vous avez de grandes requêtes, il est difficile de savoir ce que cela idsignifie partout.

Peter Eisentraut
la source
Comment nommeriez-vous la colonne pour un nom d'employé et un nom de site par exemple? Comment éviteriez-vous la redondance de la colonne d'étiquette de nom?
Spredzy
@Spredzy: J'irais simplement avec la redondance.
Peter Eisentraut
1
La réponse à ces préoccupations: les alias.
Jon of All Trades
7

Voyons voir, avec votre exemple, cela ressemblera à ceci:

USERS
----
id
username,
password
registration_date

J'utilise le nom de la table en majuscules. Cela me permet d'identifier facilement la table. Les colonnes que je viens de nommer sont chacune pour ce qu'elles représentent. J'essaie de ne pas utiliser de chiffres ou d'inclure aucun préfixe ou suffixe avec. Cela rendra les requêtes simples et assez directes.

BTW, je pense que vous devriez trouver un style que vous aimez et y rester. Si vous le modifiez souvent, vous aurez un schéma de base de données plus compliqué.

eiefai
la source
+1 pour "trouvez le style que vous aimez et respectez-le". La cohérence vaut mieux que de se conformer exactement à une norme particulière (bien que si vous n'avez pas encore choisi une norme, certaines soient meilleures que d'autres).
Jon of All Trades,
5

Comme les autres, je vous recommande de ne pas inclure le nom de la table dans la colonne. À moins que vous ayez des centaines de tables avec des noms de colonnes pour la plupart similaires: si vous avez plusieurs dizaines de tables toutes avec une colonne intitulée ID, alors préférez-les par le nom de la table.

J'ai récemment quitté une entreprise où l'un des développeurs préférait préfixer les colonnes de clé primaire et de clé étrangère avec pk et fk. Cela a conduit à certaines abominations où les colonnes ont commencé avec pkfk (généralement une clé primaire composite basée sur 2 colonnes, dont une colonne était une clé étrangère vers une autre table).

Tangurena
la source
4
cela compte-t-il comme un fk_cluster?
Kaji
5

Je travaille dans un environnement où chaque nom de colonne commence par un préfixe dérivé du nom de la table, ce n'est pas mon invention, mais j'en suis assez content.

Idéalement, les noms de colonne sont uniques sur toutes les tables de la base de données.

Quelques observations:

  • nous n'avons besoin que d'alias de table, lorsque les tables sont jointes plusieurs fois dans une instruction select
  • cela évite certaines erreurs lors de la copie d'extraits de code, car les noms de colonne doivent être adaptés au nom de la table
  • il aide à montrer à quelle table une colonne de clé étrangère pointe

Idées générales: Le plus important est la cohérence de chaque convention de dénomination: - singulier vs pluriel (ok qui s'applique aux tables et non aux colonnes) - identifier les clés primaires et étrangères (ils construisent la structure vs le contenu de la base de données) - soyez cohérent lorsque vous stockez des chaînes et une variante courte de la même chaîne - soyez cohérent avec les indicateurs, le statut, etc.

bernd_k
la source
3

Je suis d'accord avec la réponse de Spredzy, mais j'ajouterais que, par préférence, j'utiliserais camelCase au lieu de under_score.

firstName, lastName etc.

Toby
la source
2
-1 car CamelCase ne fonctionne pas dans tous les systèmes de base de données et vous n'avez pas spécifié de système de base de données. Par exemple, ses mauvaises nouvelles pour utiliser CamelCase dans Oracle (il faudrait utiliser des guillemets doubles pour le créer, mais à partir de là, tous ceux qui y accèdent devront sauter à travers des cerceaux pour y accéder / l'utiliser). Quel cauchemard.
ScottCher
@ScottCher - Je ne savais pas que cela ne fonctionne pas dans Oracle, mais je ne suis pas un DBA Oracle. J'aurais pensé qu'il serait considéré comme acquis que les noms des colonnes doivent d'abord respecter les règles définies par le DBS en question.
Toby
3

Dans le cas d'Oracle, vous voudrez ne pas nommer les colonnes 'id' ou 'name' ou quoi que ce soit de générique.

Le problème est que par défaut dans les anciennes versions , Oracle tentera de joindre les tables sur la base de noms de colonnes similaires, donc si j'ai bien nommé tout, j'ai fini par spécifier la clause de jointure par défaut entre mes tables.

Mais même si vous n'utilisez pas Oracle, en ne choisissant pas les noms qui apparaissent dans plusieurs tables, cela signifie également que vous n'avez pas à passer par la difficulté de créer un alias à chaque fois que vous devez faire une sélection sur deux tables:

SELECT
  instrument.name as instrument_name,
  instrument.abbr as instrument_abbr,
  source.name     as source_name,
  source.abbr     as source_abbr,
  ...
FROM ...

Ainsi, si les sélections multi-tables sont la norme, des noms de colonne plus longs vous évitent de taper. (si vous n'utilisez qu'une seule table à la fois ... avez-vous vraiment besoin d'une base de données relationnelle?)

... et l'enregistrement de la frappe nous amène à un autre problème dans Oracle - au moins dans 8i (la version actuelle lorsque j'ai suivi les cours Oracle SQL Tuning et Data Modeling) la mise en cache des plans d'exécution est basée uniquement sur les premiers caractères du (vous ne vous souvenez pas de la valeur exacte ... 1024?), donc si vous avez des requêtes qui ne varient que par quelque chose à la fin de la clause where, et une très longue liste de colonnes que vous extrayez, vous peut se heurter à un impact sur les performances car il ne peut pas mettre correctement en cache le plan d'exécution.

Oracle avait un guide sur la sélection de ce qu'ils prétendent être de bons noms de table et de colonne, qui est essentiellement un guide pour supprimer les lettres jusqu'à ce qu'il y ait environ 5 à 8 caractères, mais je ne m'en suis jamais beaucoup soucié.

...

Au fur et à mesure que les choses évoluent:

  • les colonnes sont toujours singulières (les tableaux sont toujours pluriels)
  • tous les noms sont en minuscules, juste au cas où quelque chose est sensible à la casse
  • en raison de ce qui précède, utilisez des traits de soulignement au lieu de l'étui à chameau.

mise à jour : pour ceux qui ne connaissent pas le comportement de jointure d'Oracle, voir le dernier exemple sur la maîtrise d'Oracle SQL: Conditions de jointure , où il mentionne:

Qu'est-il arrivé? La raison réside dans le fait que, à part fournisseur_id, ces deux tables ont une autre paire de colonnes avec un nom commun. Cette colonne est le nom. Ainsi, lorsque vous demandez une jointure naturelle entre le fournisseur et les tables de pièces, la jointure a lieu non seulement en égalant la colonne supplier_id des deux tables, mais la colonne de nom des deux tables est également équivalente. Étant donné qu'aucun nom de fournisseur n'est identique au nom de pièce de ce même fournisseur, aucune ligne n'est renvoyée par la requête.

Sous «ancienne syntaxe de jointure» (8i et versions antérieures), «NATURAL JOIN» était le comportement de jointure par défaut, et je pense qu'il l'est toujours si vous ne spécifiez pas de condition de jointure. Une fois que 'NATURAL JOIN' était une option officielle dans 9i, la recommandation générale était de ne pas l'utiliser , car un mauvais nom de colonne peut vous gâcher, ce que je préconise pour de bons noms de colonne.

Joe
la source
4
Vous parlez de «jointures naturelles» dans votre deuxième paragraphe? Si c'est le cas SHUDDER ... Dans la mesure du possible, vous devez spécifier comment vous souhaitez que votre système de base de données rejoigne vos tables. Le laisser à la base de données pour décider peut produire des résultats inattendus / incohérents. De plus, les jointures naturelles sont limitées aux jointures entre deux tables et sont donc relativement limitées dans leur facilité d'utilisation.
ScottCher
2
NATURAL JOIN n'a jamais été la valeur par défaut. Si aucune jointure explicite n'est / n'a été donnée, une jointure cartésienne serait effectuée (c'est-à-dire chaque ligne d'une table jointe à chaque ligne de l'autre table). Avant que les jointures ANSI ne soient prises en charge (c'est-à-dire celles spécifiées dans la clause FROM), les jointures devaient être effectuées dans la clause WHERE.
Gary
1
-1 pour les jointures naturelles. Lorsqu'un changement de schéma non lié peut casser des jointures, ou pire encore, les changer sans provoquer d'erreurs, vous êtes dans un monde de douleur. S'il vous plaît, pensez aux enfants et spécifiez TOUJOURS vos champs de jointure.
Jon of All Trades,
2
@ScottCher: "Laissant à la base de données le soin de décider" - tout d'abord, vous voulez probablement dire "SGBD" plutôt que "base de données". Deuxièmement, il n'y a pas d'IA ou de mécanisme anthropomorphique dans Oracle; est plutôt NATURAL JOINdéterministe.
onedaywhen
1
@Joe cross joinest, était et sera toujours le «défaut». Oracle n'a jamais correspondu au nom de la colonne, sauf s'il a natural joinété explicitement utilisé
Jack Douglas
1
  1. N'utilisez jamais de guillemets doubles "car, ce faisant, vous remplacez le casse natif de la base de données. La spécification SQL exige que tous les identificateurs soient pliés en majuscules. Certaines bases de données, comme PostgreSQL, les replient en minuscules. Si rien n'est cité, cela fonctionnera dans toutes les bases de données et ils peuvent les plier à la spécification ou à la valeur par défaut spécifique à rdbms.
  2. Utilisez un under_score ( _), car comme indiqué ci-dessus - vous ne devez pas utiliser camelCase.
  3. utiliser {entity}_idpour les identifiants (et les clés étrangères pointant vers ces identifiants). Parce qu'alors vous pouvez utiliser la USINGclause. Les noms de clés uniques au monde utilisés dans les conditions de jointure sont une convention établie dans la spécification.

    SELECT *
    FROM employee
    INNER JOIN department
      USING (department_id);
    
      -- compare to
      ON employee.department_id = department.department_id;
Neil McGuigan
la source
1
J'ai mis à jour cela pour être plus explicite.
Evan Carroll