web-dev-qa-db-fra.com

Comment stocker les statuts d'enregistrement (comme en attente, terminé, brouillon, annulé ...)

Un grand nombre d'applications nécessitent que les enregistrements de leurs tableaux aient un statut, tel que "terminé", "brouillon", "annulé". Quelle est la meilleure façon de stocker ces statuts? Pour illustrer ce que je veux en venir ici est un * très court) exemple.

J'ai une application de blog simple et chaque article a un statut: publié, brouillon ou en attente.

La façon dont je le vois, il y a 2 façons de modéliser cela dans la base de données.

  1. La table Post a un champ de texte qui inclut le texte d'état.
  2. La table Post a un champ d'état qui contient l'ID d'un enregistrement dans la table PostStatus

L'exemple de blog ici est un exemple très simple. Où une énumération (si elle est prise en charge) peut suffire. Cependant, j'aimerais que les réponses à la question tiennent compte du fait que la liste des statuts peut changer à tout moment, de sorte que d'autres pourraient être ajoutés ou supprimés.

Quelqu'un peut-il expliquer les avantages/inconvénients de chacun?

À votre santé!

Mon premier choix à ce sujet est qu'il vaut mieux utiliser une autre table et rechercher l'état comme meilleur pour la normalisation et on m'a toujours appris que la normalisation est bonne pour les bases de données

20
veganista

Le stockage de l'état sous forme d'index dans une autre table est une complication inutile. Stockez l'état directement dans le tableau de manière lisible. Dans le code d'application, utilisez des constantes ou un type d'énumération. Cela se traduira par un code d'application plus simple et facilitera le débogage de la couche de données.

Cela ne dénormalise pas les données, cela modifie simplement la représentation. Si la base de données prend directement en charge les énumérations, utilisez-la. Sinon, utilisez une contrainte pour restreindre les valeurs des colonnes. Vous allez avoir une contrainte dans les deux cas: soit une contrainte directe sur les valeurs des colonnes, soit une contrainte de clé étrangère.

Oui, vous devrez peut-être présenter l'état différemment aux différents utilisateurs. C'est un problème de présentation, à résoudre dans la couche de présentation, pas dans la couche de persistance.

15
kevin cline

Le stockage du texte d'état n'est pas une bonne idée, car quelqu'un pourrait décider que "complet" devrait être appelé "terminé" à la place et ensuite vous devez mettre à jour votre base de données, regarder dans le programme si quelqu'un a codé en dur le texte, etc.

Ce que j'ai vu dans de nombreux programmes est soit un code numérique (1 = nouveau, 2 = brouillon, 3 = en cours de validation, 4 = complet, 99 = annulé) ou un code alphanumérique court ("NOUVEAU", "DRA", "INV "," COM "," CAN "). Ce dernier rend le code (dans le programme ou dans la base de données) plus lisible par l'homme, ce qui est généralement une bonne chose. D'un autre côté, les codes numériques facilitent les comparaisons "supérieures à" ou "inférieures à", par exemple

select * from myrecords where status < Status.Complete;
10
user281377

Les trois règles des bases de données relationnelles:

  1. Normaliser
  2. Normaliser
  3. Normaliser

Donc, votre question se répond d'elle-même. Gardez le statut à l'intérieur de sa propre table et tilisez GUID/UUID comme identifiant . Les GUIDS indexés sont très rapides et résolvent les problèmes intrinsèques à l'incrémentation des nombres. Avec un identifiant, vous pouvez faire des choses intéressantes comme demander à la base de données tous les messages terminés à l'aide de l'identifiant, et parce que vous travaillez dans le paradigme relationnel db, c'est très rapide. Si vous avez juste un champ, la base de données doit faire une boucle sur chaque ligne et faire une comparaison de texte, peut-être avec un munging, et c'est très lent.

Les noms de statut de publication peuvent changer, plus d'informations sur le statut de publication peuvent être affichées dans le tableau, tout fonctionne si vous normalisez .

Par exemple, vous pouvez ajouter des niveaux d'état en tant qu'informations supplémentaires, ce qui permettrait la comparaison des mentions de munitions. Mais ils ne dépendent pas de la clé de positionnement, ce qui permet de réorganiser le niveau d'état sans nuire à l'intégrité de la base de données. Vous pouvez également insérer des niveaux supplémentaires, ce qui est assez astucieux si vous avez le niveau associé à la clé d'auto-incrémentation.

4
Spencer Rathbun

Oui, vous devriez aller avec l'option 2, avoir une table PostStatus.

Mis à part tous les avantages mentionnés dans d'autres réponses.

En gardant à l'esprit que les statuts doivent être ajoutés ou supprimés, vous pouvez avoir une colonne "activée" dans le tableau PostStatus, donc si le statut est supprimé, marquez la colonne "activée" comme "N", de cette façon, vous pourrez ajouter ou supprimer des statuts et les enregistrements existants resteront sans problème.

3
Mr Spark

Je voudrais ajouter aux réponses par ailleurs perspicaces que pour une normalisation complète, un changement dans le statut d'une entité est en fait modélisé dans une entité distincte, par ex. nommé "statusChange".

Vous auriez besoin d'une jointure supplémentaire avec l'entité statusChange, mais vous gagnez la possibilité d'ajouter des informations supplémentaires, telles que l'acteur effectuant le changement, des commentaires possibles sur la raison pour laquelle le changement s'est produit et une date à laquelle le statusChange est effectué et peut-être même quand cela devient efficace.

1
Dibbeke

L'utilisation de texte pour l'état dans le tableau d'enregistrement ne serait probablement pas une bonne idée car cela peut changer et il serait difficile d'effectuer des vérifications d'intégrité des données lors de l'insertion/mise à jour. Si vous utilisez un SGBD avec un type de données enum, vous pouvez l'utiliser à la place (les performances ne seront probablement pas compromises ... selon).

Si votre statut a besoin de métadonnées (description, créé par, nom convivial, ...), vous devrez stocker les statuts dans une table distincte et avoir une clé de statut dans votre table d'enregistrement (assurez-vous d'utiliser une clé étrangère). L'ID n'a pas nécessairement besoin d'être un nombre, juste le PK de la table d'état. De plus, si les statuts se trouvent dans leur propre table, vous pouvez les partager entre les types d'enregistrement (tables), le cas échéant. Je ne m'inquiéterais pas des problèmes de performances avec un JOIN à la table d'état.

Quoi que vous fassiez, évitez les statuts magiques (1 pour actif, 2 pour supprimé, ...). Cela repose sur la documentation et la tradition qui ont toujours tendance à se perdre sur une chronologie suffisamment longue. Si vous utilisez des identifiants numériques, assurez-vous qu'il existe une association textuelle quelque part dans votre base de données.

0
smp7d

Dépend de l'objectif de la conception de la base de données.

Si vous concevez la base de données simplement pour prendre en charge l'application (c'est-à-dire que les objets (code) sont maîtres de tous), alors utiliser une énumération (ou une énumération de pseudo pour les classes qui ne les prennent pas en charge) et stocker le nom de l'énumération est un bonne idée car vous contrôlez toujours les valeurs autorisées via l'énumération et vous rendez également le tableau un peu plus facile à lire lorsque vous êtes obligé de visualiser les données brutes (ce qui n'est pas si fréquent si le code régit réellement tout). Mais si l'énumération est signalée. Ensuite, je stocke généralement la valeur d'énumération (entier).

0
ElGringoGrande