Pourquoi la contrainte est-elle appliquée dans la base de données? Ne sera-t-il pas plus flexible de le mettre dans le code?
Je lis un livre pour débutants sur la mise en œuvre de bases de données, donc je pose la question en tant que débutant. Disons que j'ai conçu une base de données, y compris ce modèle d'entité:
entity type | sub-types
----------------+--------------------------------------------
Person | Employee, Student, ...
Student | Graduate, Undergraduate, ...
Employee | Teacher, Administrator, ...
Contraintes actuelles:
- Une personne inscrite sur le système ne peut être qu'un étudiant ou un employé.
- L'entité personne requiert l'unicité du numéro social, que nous supposons que chaque personne n'en détient qu'une seule unique (aka, une clé primaire suffisamment bonne ). (voir # 1)
Plus tard, nous décidons de supprimer le numéro 1: si un jour le collège décide que le Teacher
(le Employee
sous-type) peut également l'être Student
, en prenant des cours pendant leur temps libre, il est beaucoup plus difficile de changer la conception de la base de données qui pourrait avoir des milliers, des millions, des milliards, des millions d'entrées plutôt que de simplement changer la logique dans le code: juste la partie qui ne permettait pas à une personne d'être inscrite à la fois comme étudiant et comme employé.
(C'est très improbable mais je ne peux penser à rien d'autre pour le moment. Apparemment, c'est possible).
Pourquoi nous soucions-nous des règles métier dans la conception des bases de données plutôt que dans le code?
# 1: Une note 7 ans plus tard, un exemple concret:
j'ai vu un gouvernement où en raison d'une erreur, les SSN émis étaient dupliqués: plusieurs personnes, même SSN. Les concepteurs de la base de données d'origine ont définitivement commis cette erreur en n'appliquant pas cette contrainte d'unicité dans la base de données. (et plus tard un bogue dans l'application d'origine? plusieurs applications utilisant la base de données partagée et ne convenant pas où mettre, vérifier et appliquer la contrainte? ...).
Ce bogue continuera à vivre dans le système et tout le système développé après quoi s'appuiera sur la base de données de ce système d'origine, pendant de nombreuses années à venir. En lisant les réponses ici, j'ai appris à appliquer toutes les contraintes, autant que possible, à bon escient (pas aveuglément) dans la base de données pour représenter le monde physique réel là-bas aussi bien que possible.
la source
Réponses:
Certaines contraintes sont mieux appliquées dans la base de données et d'autres sont mieux appliquées dans l'application.
Les contraintes qui sont mieux appliquées dans la base de données sont généralement présentes car elles sont fondamentales pour la structure du modèle de données, comme une contraint de clé étrangère pour garantir la validité d'un produit
category_id
.Les contraintes qui sont appliquées dans une application peuvent ne pas être fondamentales pour le modèle de données, comme tous les produits FooBar doivent être bleus - mais plus tard, quelqu'un pourrait décider que FooBars peut également être jaune. Il s'agit d'une logique d'application qui n'a pas vraiment besoin d'être dans la base de données, mais vous pouvez créer une
colours
table distincte et la base de données peut exiger que le produit fasse référence à une entrée valide de cette table. MAIS la décision que le seul enregistrement danscolours
a la valeurblue
proviendrait encore de quelque part en dehors de la base de données.Considérez ce qui se passerait si vous n'aviez aucune contrainte dans la base de données et exigiez qu'elles soient toutes appliquées dans l'application. Que se passerait-il si vous aviez plus d'une application qui devait travailler avec les données? À quoi ressembleraient vos données si les différentes applications décidaient d'appliquer différemment les contraintes?
Votre exemple montre une situation où il aurait été plus avantageux d'avoir la contrainte dans l'application plutôt que dans la base de données, mais peut-être y avait-il un problème fondamental avec le modèle de données initial étant trop restrictif et rigide?
la source
teachers_as_students
qui est un autre sous-type deStudents
et a une nouvelle clé étrangère en référenceTeachers
et une clé primaire générée par le système , au lieu d'une Social Numéro de sécurité. De cette façon, un "élève" est en fait un alias pour un enseignant afin que l'enseignant puisse toujours s'inscrire pour suivre un cours. Il est difficile de dire avec certitude dans quelle mesure cela fonctionnerait sans voir l'ensemble du modèle de données.color_products
, etcolor
, vous pourrez probablement créer les listes déroulantes supplémentaires avec plus de facilité - la plupart des IDE / chargeurs de schéma, prennent en charge les fkeys suivants.Car:
Juste quelques raisons qui sont importantes pour moi.
la source
Les données survivront probablement longtemps au code d'application. Si la règle est essentielle à l'utilité des données dans le temps (comme les contraintes de clé étrangère qui aident à maintenir l'intégrité des données), elle doit se trouver dans la base de données. Sinon, vous risquez de perdre la contrainte dans une nouvelle application qui frappe la base de données. Non seulement plusieurs applications atteignent les bases de données (y compris certaines qui ne réalisent pas qu'il existe une règle de données importante), mais certaines d'entre elles telles que les importations de données ou les applications de génération de rapports peuvent ne pas être en mesure d'utiliser la couche de données configurée dans l'application principale de saisie de données. Franchement, les chances qu'il y ait un bogue dans la contrainte sont beaucoup plus élevées dans le code d'application selon mon expérience.
À mon avis personnel (sur la base de plus de 30 ans de traitement des données et de l'expérience avec des centaines de bases de données différentes utilisées à de nombreuses fins différentes), quiconque ne place pas les contraintes dans la base de données à laquelle il appartient aura finalement des données médiocres. Parfois de mauvaises données au point d'être inutilisables. Cela est particulièrement vrai lorsque vous disposez de données financières / réglementaires qui doivent répondre à certains critères d'audit.
la source
La plupart des contraintes d'intégrité référentielle qui sont implémentées en dehors de la base de données peuvent être supprimées, donc si vous voulez que vos données aient une intégrité garantie à tout moment, vous devez appliquer des contraintes dans la base de données. Arrêt complet, c'est tout.
En règle générale, les contraintes au niveau de l'application sont supprimées via le mécanisme de cohérence de lecture de la base de données, par lequel les sessions ne peuvent pas afficher les données des autres sessions jusqu'à ce qu'elles soient validées.
Par exemple, deux sessions peuvent essayer d'insérer la même valeur dans une colonne destinée à être unique. Ils peuvent tous deux vérifier en même temps que la valeur n'existe pas déjà, peuvent à la fois insérer leur valeur et peuvent tous les deux valider. Une contrainte unique implémentée dans la base de données ne laisserait pas cela se produire.
Au fait, cela n'est pas inconnu des concepteurs de langage d'application. Lisez la section 3.10 unicité dans les guides Ruby on Rails: validations d'enregistrements actifs et rappels
la source
Avantages des contraintes imposées par la base de données:
Simplicité - Déclarer une contrainte est beaucoup plus simple que de déclarer une contrainte et d'écrire le code qui appliquera cette déclaration.
Précision - Le code que vous n'avez pas écrit n'aura jamais de bug que vous avez créé. Les fournisseurs de bases de données passent du temps à s'assurer que leur code de contrainte est précis, vous n'avez donc pas à le faire.
Vitesse - Votre application ne peut jamais avoir plus de distributions que la base de données sur laquelle elle est basée. Les fournisseurs de bases de données passent du temps à s'assurer que leur code de contrainte est efficace, vous n'avez donc pas à le faire. La base de données elle-même a également un accès plus rapide aux données qu'une application ne pourrait jamais avoir, peu importe son efficacité.
Réutilisation - Vous pouvez commencer avec une seule application sur une seule plate-forme, mais cela peut ne pas rester ainsi. Et si vous avez besoin d'accéder aux données à partir d'un système d'exploitation différent, d'un matériel différent ou d'une interface vocale? En ayant des contraintes dans la base de données, ce code n'a jamais à être réécrit pour la nouvelle plate-forme et n'a jamais à être débogué pour la précision ou profilé pour la vitesse.
Exhaustivité - Les applications imposent des contraintes lorsque les données sont entrées dans la base de données et nécessiteraient des efforts supplémentaires pour vérifier l'exactitude des données plus anciennes ou pour manipuler les données déjà présentes dans la base de données.
Longévité - Votre plate-forme de base de données survivra probablement à toute application particulière.
la source
Pourquoi des contraintes sont-elles appliquées sur le serveur? Parce que vous ne pouvez pas forcer les méchants à utiliser votre client.
Pour clarifier, si vous ne faites que le traitement des règles métier dans votre application client, une personne utilisant un autre outil peut se connecter au serveur de base de données et faire ce qu'elle veut sans être contraint par l'une de vos règles métier et des contrôles d'intégrité. Il est très difficile d'empêcher quiconque d'utiliser un outil arbitraire n'importe où sur le réseau.
Si vous effectuez la vérification d'intégrité sur le serveur de base de données, chaque tentative d'accès aux données, quel que soit l'outil, sera limitée par vos règles.
la source
Quelques bonnes réponses ici, et au risque de répéter d'autres pensées:
UPDATE
instruction directement sur la base de données, comment votre application empêche-t-elle une modification non valide? Un autre problème avec les règles métier dans l'application est que la recompilation / redéploiement peut être difficile, en particulier pour les applications distribuées où il est possible que tout le monde ne reçoive pas la mise à jour en même temps. Et enfin, la modification des règles métier dans l'application ne fait absolument rien sur les données existantes qui violent les nouvelles règles - si vous ajoutez la nouvelle contrainte aux données, vous devez corriger les données.Dans le cas que vous mentionnez explicitement, où vous autorisez soudainement quelque chose qui n'était pas autorisé auparavant, ce n'est pas vraiment un problème - vous supprimez toutes les contraintes qui l'ont imposé, peu importe où cela existe. Dans le cas contraire, où soudainement les enseignants ne sont plus autorisés à être des étudiants, vous avez potentiellement un tas de données à nettoyer, là encore indépendamment de l'endroit où la contrainte existait auparavant.
la source
La base de données peut vérifier efficacement les contraintes. Mieux que le code.
Les contraintes d'intégrité aident la base de données à trouver un plan d'exécution efficace
L'application voit une vue cohérente en lecture, donc elle peut difficilement garantir l'unicité. La base de données peut également voir des données non validées.
la source
Réponse courte ... pour préserver l'intégrité des données (c'est-à-dire l'exactitude et la validité).
Une exception ...
Si la base de données stocke simplement les données d'une seule application pour un seul utilisateur, comme dans la plupart des bases de données Sqlite, elle peut ne pas avoir besoin de contraintes. En fait, ils ne le font généralement pas, afin de garder le temps d'accès si rapide qu'il est incommensurable.
Pour tout le reste ... Les
bases de données servent toujours deux maîtres que j'appellerai éditeurs et utilisateurs .
Les éditeurs mettent principalement des données dans la base de données et récupèrent les données un ou un petit nombre d'enregistrements à la fois. Leurs principales préoccupations sont un accès rapide et précis à toutes les données associées et un stockage rapide et fiable de leurs modifications.
Les utilisateurs récupèrent principalement des données et sont plus soucieux d'un accès rapide à des informations incontestablement précises. Ils ont souvent besoin de divers comptes, agrégations et listes qui étaient auparavant générés dans ces piles emblématiques d'une épaisseur d'un pied d'impressions de papier barre verte, mais qui se retrouvent généralement sur les pages Web aujourd'hui.
Les projets de développement de bases de données sont presque toujours lancés à la demande des utilisateurs , mais la conception est motivée par les besoins de saisie des données et d'enregistrement à la fois des éditeurs . Ainsi, les développeurs inexpérimentés répondent souvent au besoin immédiat de rapidité (principalement de développement ) en ne mettant pas de contraintes dans la base de données.
Si une et une seule application doit être utilisée pour apporter des modifications aux données pendant toute la durée de vie de la base de données, et que cette application est développée par une ou un petit nombre d'individus bien coordonnés, alors il pourrait être raisonnable de s'appuyer sur l'application pour assurer l'intégrité des données.
Cependant, autant que nous prétendons pouvoir prédire l'avenir, nous ne le pouvons pas.
L'effort pour produire une base de données est trop précieux pour la jeter. Comme une maison, la base de données sera agrandie, modifiée et rénovée plusieurs fois. Même lorsqu'elle est complètement remplacée, toutes les données seront migrées vers la nouvelle base de données tout en préservant toutes les anciennes règles et relations commerciales.
Les contraintes implémentent ces règles et relations sous une forme déclarative concise dans le moteur de base de données lui-même où elles sont facilement accessibles. Sans eux, les développeurs ultérieurs devraient parcourir les programmes d'application pour procéder à une rétro-ingénierie de ces règles. Bonne chance!
D'ailleurs, c'est exactement ce que les programmeurs COBOL mainframe doivent faire, car ces bases de données massives ont souvent été créées avant que nous ayons des moteurs relationnels et des contraintes. Même en cas de migration vers un système moderne comme DB2 d'IBM, les contraintes ne sont parfois pas entièrement mises en œuvre car la logique des anciennes règles, incorporées peut-être dans une série de programmes "batch" COBOL, peut être si compliquée qu'elle n'est pas pratique à convertir. Des outils automatisés peuvent à la place être utilisés pour convertir l'ancien COBOL en une version plus récente avec des interfaces vers le nouveau moteur relationnel et avec un petit ajustement, l'intégrité des données est préservée ... jusqu'à ce qu'une nouvelle application soit écrite qui corrompt subtilement tout et que l'entreprise soit transportée en justice pour, disons, empêcher des milliers de propriétaires de maison qu'ils ne devraient pas avoir.
la source
En plus des autres commentaires ...
Si / lorsque vous avez une base de données où une table donnée peut être mise à jour par une ou plusieurs applications ou chemins de code, le fait de placer les contraintes appropriées dans la base de données signifie que vos applications ne dupliqueront pas le "même" code de contrainte. Cela vous profite en simplifiant la maintenance (en réduisant le nombre d'emplacements à modifier en cas de changement de modèle de données) et en garantissant que les contraintes sont appliquées de manière cohérente quelle que soit l'application mettant à jour les données.
la source
Personnellement, je pense qu'il est plus facile de créer et de modifier des contraintes que de créer des déclencheurs, par exemple, ce qui serait un moyen d'appliquer votre règle métier à l'aide du code source.
Les déclencheurs sont également moins susceptibles d'être portables, car ils sont généralement écrits dans des langages spécifiques au fournisseur, tels que PL / SQL.
Mais si les contraintes ne répondent pas à vos besoins, vous pouvez toujours utiliser des déclencheurs pour appliquer vos règles métier.
la source
Ils doivent toujours être appliqués dans la base de données en premier parce que,
varchar(5)
type, il y a de fortes chances que vous puissiez trouver un schéma de chargement ORM pour votre langue spécifique qui mappe le type de langue au type de schéma et assemble sa propre contrainte de taille.DBIx for Perl is one such schema loader
; en voici une autre pour Entity Framework . Les capacités de ces chargeurs varient, mais tout ce qu'ils peuvent fournir est un bon début pour assurer l'intégrité de l'application sans se rendre à la base de données.la source