Je dois d'abord préciser que la colonne d'état n'est pas destinée à refléter l'état d'un élément réel représenté par l'enregistrement (ligne) dans le tableau. Il vise plutôt à montrer l'état de l'enregistrement lui-même.
Il peut être aussi simple que actif / inactif ou compliqué comme approuvé / supprimé / Verrouillé / En attente / Rejeté, etc. L'état peut être stocké sur un booléen / courte colonne entière ou une colonne d'un seul caractère, avec correspondances comme true
/ 1
= active ou A
= Approuvé.
L'idée de base est d'avoir un support de récupération de type corbeille / corbeille dans l'application (et de le simuler dans la base de données). S'il existe une interface graphique frontale ou une autre interface qui peut soi-disant permettre à un utilisateur de "supprimer" des enregistrements, il ne supprime pas réellement l'enregistrement dans la table, mais modifie simplement l'état de l'enregistrement en Inactif ou Supprimé. Lorsque l'interface récupère des enregistrements, elle obtient toujours les enregistrements qui correspondent uniquement à la condition selon laquelle l'état est Actif ou Approuvé.
Si l'utilisateur fait une erreur et que l'enregistrement "supprimé" (du point de vue de l'utilisateur) doit être récupéré, un administrateur de base de données peut facilement corriger l'enregistrement en étant actif ou approuvé, ce qui serait mieux que de rechercher des sauvegardes et, espérons-le, de trouver l'enregistrement d'origine Là. Ou l'interface elle-même peut permettre à l'utilisateur d'afficher les enregistrements supprimés dans une vue distincte, et de les restaurer selon les besoins, ou même de les supprimer définitivement (suppression de l'enregistrement réel).
Mes questions:
- Est-ce une bonne ou une mauvaise pratique?
- Cela affecte-t-il la normalisation des données?
- Quels sont les pièges potentiels?
- Existe-t-il une autre méthode pour atteindre le même objectif? (voir la note)
- Comment pouvez-vous faire en sorte que la base de données applique des contraintes uniques sur les données pour un certain statut uniquement (mais autorise un nombre illimité de doublons pour d'autres statuts)?
- Pourquoi les bases de données ne fournissent-elles pas une fonctionnalité de type «corbeille» ou un suivi / récupération de table en mode natif, afin que nous puissions laisser les interfaces supprimer les enregistrements réels sans souci?
Remarque: J'ai lu sur la gestion d'une table d'historique distincte, mais cela semble pire en termes de stockage et d'avoir à générer des déclencheurs et à maintenir les déclencheurs à jour avec le schéma de la table suivie.
la source
Réponses:
Je le connais comme un "Soft Delete"; il suffit de marquer un enregistrement comme "supprimé", même s'il ne l'est pas vraiment.
Ça dépend.
Si c'est quelque chose dont vos utilisateurs ont besoin [beaucoup], c'est probablement une bonne chose. Dans la grande majorité des cas, cependant, je dirais que cela ajoute [beaucoup] de frais généraux pour peu d'avantages.
Non, mais il aura une incidence sur votre indexation de ces données.
Assurez-vous d'inclure la colonne "supprimé" dans vos index, afin que ces lignes soient exclues le plus tôt possible dans vos requêtes.
Vos données deviennent un peu plus complexes. Tout ce qui se rapproche des données doit "connaître" ces enregistrements supplémentaires, "pas vraiment là". Ou, vous devez créer des vues sur les tables qui excluent ces lignes et utiliser ces vues dans, disons, votre outil de création de rapports préféré.
Votre base de données peut augmenter en taille. Si vous ne supprimez pas vraiment ces lignes, elles sont toujours là, occupant de l'espace. Cela peut ou non être un problème, d'autant plus que vous les avez inclus dans vos index, donc l'espace qu'ils consomment est multiplié.
Non, pas vraiment.
Pas facilement. L'intégrité référentielle déclarative (clauses de clé étrangère) est le moyen le plus propre de l'implémenter et il est facile pour des choses comme les outils de création de rapports de reprendre ces règles pour déterminer les relations entre les tables. Ces règles s'appliquent à tous les enregistrements, quel que soit leur "statut" (et il n'y a aucun moyen de contourner cela).
L'alternative consiste à utiliser des déclencheurs, des extraits de code procédural qui renforcent l'intégrité référentielle entre les tables et effectuent toutes les tâches intelligentes et conditionnelles dont vous avez besoin. C'est bon pour votre cas particulier, mais la plupart des avantages de Declarative RI sortent de la fenêtre - il n'y a pas de relations [externes] détectables entre vos tables; c'est tout "caché" dans les déclencheurs.
Pourquoi le feraient- ils?
Ce sont des bases de données, après tout, pas des systèmes de fichiers ou des feuilles de calcul.
Ce qu'ils font, ils [peuvent] le faire très, très bien.
Ce qu'ils ne font pas, il n'y a probablement pas eu beaucoup de demande.
la source
C'est une pratique. Que ce soit bon ou mauvais dépend fortement de votre application et de la fréquence à laquelle vous allez vraiment avoir besoin / vouloir faire une "suppression". Je serais assez douteux d'un plan pour mettre ce type de colonne de chaque table dans le système - il semble très peu probable que vous vous donniez vraiment la peine d'implémenter la suppression de suppression sur chaque table du système. Et cela nécessite une implémentation - dans la grande majorité des cas, vous ne supprimez pas une seule ligne d'une seule table, vous devez parcourir les tables enfants en supprimant les lignes et en mettant à jour les tables associées.
Pour la plupart des autres questions, cela dépend fortement de l'implémentation. Par exemple, Oracle fournit différentes méthodes pour suivre toutes les modifications apportées à une table - Flashback Data Archive (FDA également connu sous le nom de Total Recall) étant l'approche la plus récente pour maintenir un historique complet de chaque version d'une ligne et l'archivage dans la base de données pour la mise en œuvre le motif de suppression progressive. D'autres bases de données peuvent fournir d'autres moyens d'implémenter le modèle. En fonction de la base de données et de la façon dont vous implémentez la suppression logicielle, il y aura divers impacts sur les performances, si et comment les contraintes peuvent être appliquées, etc. Si nous parlons d'Oracle, vous pouvez faire beaucoup avec les index basés sur les fonctions, par exemple , dans SQL Server, vous pouvez souvent utiliser des index filtrés à des fins similaires.
la source
Il est très courant d'utiliser un champ "marqué pour suppression" dans les systèmes MRP / ERP.
Par exemple, on peut vouloir marquer un enregistrement de pièce ou d'inventaire qui n'est plus vendu comme inactif, mais il y a encore des commandes en cours qui lui sont associées. Effectuer une véritable suppression de l'enregistrement peut affecter les commandes qui n'ont pas encore été expédiées, les entrées de grand livre qui n'ont pas encore été enregistrées, les tables d'historique qui ne seront pas construites avant la fin du mois, etc. De nombreux systèmes interdiront la suppression d'un enregistrement à moins qu'il ne passe une série de validations par rapport à d'autres tables. Si vous supprimez en cascade vos relations, une véritable suppression peut être encore plus destructrice.
Au lieu de cela, en le marquant pour suppression, vous placez un marqueur d'intention clair sur l'enregistrement et, plus tard, une tâche planifiée peut supprimer l'enregistrement s'il vérifie que toutes les tables associées ne le référencent plus.
Un cas similaire pourrait être fait pour cette fonctionnalité sur une table client et d'autres tables "à long terme". Cela a même du sens sur des tables plus volatiles comme les commandes, bien que le nom du drapeau puisse devenir quelque chose comme "expédié" ou "annulé". Il remplit la même fonction: ne le supprimez pas cette seconde, mais utilisez-le comme indicateur pour le programme de purge afin qu'il tente de valider la suppression de l'enregistrement à l'avenir.
la source
Comme solution alternative, l'utilisation du sourcing d'événements permet des objectifs similaires sans compliquer la structure de la table, bien que cela rend le code de modification de vos données un peu plus complexe, car vous devez écrire la modification dans un événement qui peut être conservé dans l'historique des événements. . Cela vous permet ensuite de recréer la base de données telle qu'elle était à un moment donné, ce qui peut être une fonctionnalité très utile.
(Je ne crois pas que ce soit ce que vous vouliez dire par "table d'historique", ce que je pense que vous vouliez simplement copier les enregistrements modifiés ou supprimés dans une autre table avant de les changer)
la source
Je vois et utilise fréquemment ce modèle pour ces cas d'utilisation:
Le problème consiste à appliquer l'intégrité des données si plusieurs applications ou services Web écrivent dans des tables. Comment vous assurez-vous que pour un cas il n'y a qu'un seul état actuel? Comme le souligne Justin Cave, cela peut être fait dans Oracle en créant un index virtuel basé sur une fonction, mais cette surcharge supplémentaire pour ce qui semblait à l'origine un concept simple.
la source
C'est une bonne pratique si vous prévoyez d'utiliser vos données pour la génération de rapports (toute application suffisamment grande devrait avoir des rapports).
Afin d'accélérer votre application, vous ne devez vraiment pas laisser les outils de reporting s'exécuter sur votre base de données. En tant que tel, vous devez effectuer une copie / synchronisation vers une autre base de données.
J'utilise
recordStatus
seulement deux étatsACTIVE
ouCANCELLED
en combinaison avec unlastUpdatedOn
horodatage. J'utiliserecordStatus
plutôt questatus
ce qui a généralement un sens commercial.Lorsque je synchronise la base de données de génération de rapports avec l'application, je filtre les informations
lastUpdatedOn
pour savoir lesquelles je vais remplacer du côté des rapports.En ce qui concerne les rapports, je n'aurai pas les champs
recordStatus
oulastUpdatedOn
car ils ne seront généralement pas signalés. En tant que tel, lorsque je vois unCANCELLED
statut, je supprimerais l'enregistrement du côté du rapport de cette façon, il n'a que des enregistrements actifs.Cela peut être étendu à d'autres types de magasins tels que les archives ou les sauvegardes où une synchronisation presque complète est requise. Cependant, la notification est l'objectif le plus courant.
Notez votre exemple
Approved
,New
,Pending
n'est pas une bonne idée de mettre un champ commun comme qui a une entreprise qui signifie qu'il devrait aller que là où il fait des affaires de sens sage.Quant à verrouillé, utilisez
versionNo
ce qui fournit un verrou optimiste pour votre dossier.Une autre option au lieu de
recordStatus
est derecordActive
le stocker comme unboolean
qui prend moins d'espace et moins d'indexation, mais je serais préoccupé par les besoins futurs que vous ne pouvez pas prévoir.la source