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

18

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

veganista
la source
Qu'entendez-vous par «à tout moment»? Cela signifie-t-il dans le cadre de l'activité de l'utilisateur ou dans le cadre du cycle de sortie du logiciel?
kevin cline
Les deux, dans quels cas l'une des approches mentionnées ici est-elle la mieux utilisée? Donc, si les utilisateurs peuvent ajouter de nouveaux statuts, ou si de nouveaux statuts sont ajoutés à un stade ultérieur du projet
veganista
Le stockage du texte dans la base de données peut être une bonne dénormalisation. Je pense que cela peut dépendre de détails précis, par exemple à quelle fréquence votre organisation change-t-elle ses processus (conduisant à d'éventuels changements de statut)?
Jaydee
Si les utilisateurs sont en mesure d'ajouter de nouveaux statuts, c'est tout autre chose. Vous voudrez probablement enregistrer l'utilisateur créateur etc. avec le statut et aurez certainement besoin d'une autre table.
kevin cline

Réponses:

14

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.

Kevin Cline
la source
1
+1, à moins d'un besoin spécifique de conserver la liste des statuts dans la base de données, c'est généralement la manière la plus simple et la moins compliquée de le faire.
GrandmasterB
2
C'est correct, à moins que vous ne commenciez à changer l'architecture de statut ou à stocker des dates de mutation
LastT Tribunal
10

Stocker le 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 = terminé, 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;
user281377
la source
Un idiot peut aussi hardcore l'ID.
Morons
Un autre avantage des ID est que vous devez fournir la localisation. Vous pouvez utiliser votre ID pour rechercher la chaîne de ressources et l'afficher. Avec des chaînes codées en dur, ce n'est pas possible
armitage
3
Je ne pense pas que faire des statuts en utilisant des comparaisons "supérieures à" ou "inférieures à" comme vous l'avez montré est une bonne idée. Cela peut fonctionner pour des applications plus simples telles que cet exemple mais n'est pas bon pour des applications plus complexes (bien que je suis sûr que vous en soyez conscient)
veganista
1
@armitage: il est parfaitement possible d'effectuer une recherche à l'aide de chaînes. Les noms des ressources sont des chaînes:status.draft=Draught
kevin cline
veganista: Bien sûr, il peut y avoir des difficultés avec des comparaisons plus grandes / plus petites que les comparaisons, mais j'ai vu de grands systèmes complexes qui font cela et vivent.
user281377
4

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

  1. Normaliser
  2. Normaliser
  3. Normaliser

Votre question se répond donc d'elle-même. Gardez le statut à l'intérieur de sa propre table et utilisez les 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 en utilisant l'identifiant, et parce que vous travaillez dans le paradigme relationnel de la base de données, 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 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.

Spencer Rathbun
la source
Les raisons que vous avez indiquées ici sont exactement les raisons pour lesquelles j'utilise une autre table pour stocker mes arrêts. La principale raison pour laquelle j'ai posé cette question est de voir s'il est parfois utile d'utiliser un champ de texte plus simple.
veganista
@Liam Uniquement s'il se normalise dans un champ de texte. Autrement dit, si votre champ de texte dépend uniquement de la clé primaire et que vous recherchez des éléments en fonction de la clé primaire , le champ de texte venant. Une base de données relationnelle concerne les relations, vous en avez une ici, elle doit donc être définie. L'une des rares exceptions est si vous manipulez des données sales à partir d'une source externe et que vous n'avez pas le temps de les modéliser complètement. Évitez cela si possible.
Spencer Rathbun
cache les yeux, pleurant les GUID qui ne reviendront jamais
sq33G
Vous devriez avoir écrit "trois théories des bases de données relationnelles". La théorie n'est pas toujours pratique. Il est souvent plus efficace de stocker un code d'état directement dans l'enregistrement auquel il est lié. Si vous n'avez pas besoin de le rechercher pour l'utiliser, la suppression de la jointure vers une autre table permet d'économiser beaucoup de traitement.
Suncat2000 du
Voté en raison d'informations erronées sur les types de colonnes par rapport aux analyses de table complètes.
igorrs
3

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.

Mr Spark
la source
1

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 exemple nommée '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 éventuellement même quand cela devient efficace.

Dibbeke
la source
0

L'utilisation de texte pour le statut dans la table 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 une documentation et une 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.

smp7d
la source
Si vous ne vous inquiétez pas des performances, vous sacrifiez probablement l'évolutivité. Il est impossible pour les ordinateurs d'éviter les états magiques: 0 et 1 sont intrinsèquement magiques.
Suncat2000
0

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 tout). Mais si l'énumération est signalée. Ensuite, je stocke généralement la valeur d'énumération (entier).

ElGringoGrande
la source
-1

Le statut est très important, chaque fois que vous obtenez des informations de publication, vous devrez obtenir son statut, ou vous voudrez filtrer les publications par statut. Si vous avez un statut dans une autre table, vous devrez faire des jointures pour obtenir ces informations et ainsi les performances sont compromises. Certainement, vous devriez avoir le statut dans la même table. Et mettez un index dessus! Vous pouvez toujours utiliser des nombres entiers comme statut, ou peut-être un champ enum.

dxvargas
la source
-2

La bonne solution consiste à utiliser un magasin / source d'événements avec CQRS ou une blockchain. Le problème avec la capture d'événements dans un RDB est que le RDB stocke un instantané d'un seul événement dans le temps, et des choses comme "Statuts / Etats" sont des séquences de mutations qui évoluent avec le temps

LastT Tribunal
la source
Si vous allez voter contre mon poste, alors faites un cas. Sinon, vous êtes juste un lemming à l'esprit doux qui a très peu de portée en dehors de la boîte
LastT Tribunal