web-dev-qa-db-fra.com

Type à utiliser pour les colonnes "Status" dans une table sql

J'ai une structure de table (factice) comme suit:

billet
 identifiant: int (11) PK 
 prénom: varchar (255) 
 statut: ????????? 

La question est, quel type de données dois-je utiliser pour le statut? Voici mes options, telles que je les vois:

  1. varchar représentant le statut - MAUVAIS car il n'y a pas d'intégrité
  2. enum représentant le statut - MAUVAIS parce que pour changer la valeur, il faudrait que je modifie la table, puis n'importe quel code avec des listes déroulantes pour les valeurs, etc., etc.
  3. int FK vers une table d'état - BON parce que c'est dynamique, MAUVAIS parce qu'il est plus difficile d'inspecter à vue (ce qui peut être utile)
  4. varchar FK vers une table d'état - BON car dynamique et visible lors de l'inspection. MAUVAIS parce que les clés ont un sens, ce qui est généralement mal vu. Fait intéressant, dans ce cas, il est tout à fait possible que la table de statut ne comporte qu'une colonne, ce qui en fait une énumération glorifiée.

Ai-je eu une lecture précise de la situation? Avoir une clé significative est-il vraiment si mauvais? Parce que bien que cela me donne la chair de poule, je n'ai aucune raison de le faire ...

Mise à jour: Pour l'option 4, la structure proposée serait status : char (4) FK , dans une table de statuts. Alors,

OPEN => "Open"

CLOS => "Fermé"

"PEND" => "En attente d'autorisation"

"PROG" => "En cours

Quel est l'inconvénient dans ce cas? Dans ce cas, le seul avantage que l’on puisse constater lorsqu’on utilise int over char est une légère performance.

23
XwipeoutX

Allez avec le numéro 3. Créez une vue qui rejoint la valeur de statut si vous voulez quelque chose d'inspectable.

5
Ian Jacobs

J'irais avec le numéro 4, mais j'utiliserais une colonne char(x). Si vous êtes préoccupé par les performances, un caractère (4) occupe autant d’espace (et du moins on pourrait le penser, une entrée/sortie disque, une bande passante et un temps de traitement) en tant qu’int, ce qui nécessite également 4 octets à stocker. Si vous êtes vraiment préoccupé par la performance, faites-en un caractère (2) ou même un caractère (1).

Ne le considérez pas comme une "donnée significative", considérez-le comme une abréviation de la clé naturelle. Oui, les données ont un sens, mais comme vous l’avez remarqué, cela peut être une bonne chose de travailler avec les données - cela signifie que vous n’aurez pas toujours à vous joindre (même si vous utilisez une petite table) pour extraire le sens du base de données. Et bien sûr, la contrainte de clé étrangère garantit la validité des données, car elles doivent figurer dans la table de recherche. (Cela peut également être fait avec les contraintes CHECK, mais les tables de recherche sont généralement plus faciles à gérer et à maintenir dans le temps.)

L'inconvénient est que vous pouvez essayer de trouver un sens. char (1) a un fort attrait, mais si vous atteignez dix valeurs ou plus, il peut être difficile de trouver des valeurs bonnes significatives. Moins de problème avec char (4), mais reste un problème possible. Un autre inconvénient: si les données sont susceptibles de changer, alors oui, vos données significatives ("PEND" = "Autorisation en attente") peuvent perdre leur signification ("PEND" = "Transmettre au bureau principal pour approbation initiale"). C'est un mauvais exemple. Si des codes comme celui-ci changent, vous feriez bien mieux de refactoriser votre système pour refléter le changement des règles commerciales. Je suppose que mon objectif devrait être le suivant: s'il s'agit d'une valeur de recherche saisie par l'utilisateur, les clés de substitution (entiers) seront votre ami, mais si elles sont définies et maintenues en interne, vous devez absolument prendre en compte des valeurs plus respectueuses de l'homme. Cela, ou vous aurez besoin de notes post-em sur votre moniteur pour vous rappeler ce que le diable Status = 31 est censé vouloir dire. (J'en ai trois sur le mien et le stickum s'use tous les deux ou trois mois. On parle de coût d'entretien ...)

6
Philip Kelley

Je voudrais utiliser un INT et créer une relation de clé étrangère à la table d'état. Un INT devrait certainement être sans danger pour une colonne d'état énuméré.

5
James Johnson

Puis-je vous recommander d’utiliser un champ statusID et d’avoir une table séparée mappant l’ID à un varchar?

EDIT: Je suppose que c'est exactement ce que vous avez décrit au point 3. Je pense que c'est la meilleure option.

3
Jon Martin

Je suppose que votre base de données a une partie de description et que les utilisateurs normaux ne sont pas exposés au code de statut.

Votre commodité ne concerne donc que les programmeurs et les administrateurs de base de données - des personnes importantes, mais je ne voudrais pas optimiser ma conception pour eux.

Plus fort - Je ferais très attention à utiliser des abréviations "significatives" - le gâchis de données le plus flagrant que j'aie jamais vu s'est produit lorsqu'un développeur nettoyait certaines données et interprétait la clé "significative" de manière incorrecte; s’avère que "PROG" ne signifie pas "programmé", mais "en cours".

Aller avec l'option 3.

3
Neville Kuyt

La création d'une table séparée avec un statut est une bonne idée lorsque vous souhaitez afficher la liste des statuts dans le formulaire HTML. Vous pouvez afficher la description détaillée de la table de consultation et aider l'utilisateur à choisir le statut si les conditions requises sont les mêmes.

Du point de vue du développement, je voudrais utiliser un nombre entier comme clé primaire. Vous pouvez l'optimiser en utilisant un entier petit/minuscule si vous savez qu'il ne dépassera pas la limite.

Si vous utilisez l'abréviation en tant que clé étrangère, vous devez penser à la rendre unique en permanence, car @Philip Kelley en a parlé comme d'un inconvénient.

Enfin, vous pouvez déclarer le type de table MYISAM si vous le souhaitez.

Mise à jour: Reflétant l'opinion de @Philip Kelley, s'il y a trop de statuts, il est préférable d'utiliser un entier comme clé étrangère. S'il y a seulement deux statuts, alors peut être utiliser abbr comme clé étrangère.

0
kta

J'ai récemment travaillé avec un grand nombre de bases de données nécessitant beaucoup d'états ET j'ai quelques notes qui pourraient valoir la peine d'être ajoutées à la conversation.

INT: L'une des choses que j'ai constatées est que, si une application utilise beaucoup de suivi, le nombre de tables de référence peut rapidement devenir compliqué et, comme vous l'avez mentionné, effectuer une inspection de la base de données à un endroit donné. coup d'œil peu pratique. (Ce qui, pour certains de mes clients, compte beaucoup plus que les maigres millisecondes économisées en temps de traitement.)

VARCHAR: Terrible idée de programmation, mais il est important de déterminer si un statut donné sera utilisé par le code ou simplement par des yeux humains. Pour ces derniers, vous bénéficiez d'une portée illimitée et ne devez entretenir aucune relation.

CHAR (4): L'utilisation d'une colonne de caractères descriptive peut en fait être une très bonne approche. En règle générale, je ne le considérerais que si la plage de valeurs devait être basse et évidente, mais uniquement parce que je considère cette approche comme non standard (risque de confusion pour les nouveaux développeurs). De manière réaliste, vous pouvez utiliser une valeur CHAR comme clé étrangère de la même manière qu’un INT, gagner en lisibilité et maintenir la parité des performances.

La seule chose que vous ne pourriez pas faire et qui me manquerait, ce sont les opérations mathématiques (comme "<" et ">").

INT Range: Une stratégie hybride que j'ai essayée consiste à utiliser INT, mais en ajoutant un certain degré de sémantique aux nombres. Donc, par exemple,

1-10 being for initial stages, 
11-20 being in progress, and 
21-30 being the final stages. 
60-69 for errors, rejections

Le problème ici est que si vous découvrez que vous avez besoin de plus de nombres, vous êtes SOL, car la prochaine plage est déjà prise. Donc, ce que j'ai fini par faire était (en quelque sorte) d'imiter les réponses HTTP:

100-199 being for initial stages, 
200-299 being in progress, and 
300-399 being the final stages. 
500-599 for errors, rejections

Je préfère ceci à un simple INT, et bien que can soit moins descriptif que CHAR, il peut aussi être moins ambigu. Alors que "PROG" peut signifier un certain nombre de choses, bonnes, mauvaises ou bénignes, si je peux voir que quelque chose se situe dans la gamme 500, je ne saurai peut-être pas quel est le problème, je serai en mesure de vous le dire est un problème.

0
DevBodin