Warum werden Einschränkungen in der Datenbank angewendet? Wird es nicht flexibler sein, es in den Code einzufügen?
Ich lese ein Einsteigerbuch über die Implementierung von Datenbanken und frage dies als Anfänger. Angenommen, ich habe eine Datenbank mit folgendem Entitätsmodell entworfen:
entity type | sub-types
----------------+--------------------------------------------
Person | Employee, Student, ...
Student | Graduate, Undergraduate, ...
Employee | Teacher, Administrator, ...
Aktuelle Einschränkungen:
- Eine im System registrierte Person kann nur ein Student oder ein Mitarbeiter sein.
- Die Entität einer Person erfordert die Eindeutigkeit einer sozialen Zahl, von der wir annehmen, dass jede Person nur eine einzige eindeutige besitzt (auch bekannt als ein ausreichend guter Primärschlüssel). (siehe # 1)
Später beschließen wir, die Nummer 1 zu entfernen: Wenn das College eines Tages beschließt, dass der Teacher
(der Employee
Untertyp) auch sein Student
kann, Kurse in ihrer Freizeit zu belegen, ist es viel schwieriger, das Datenbankdesign zu ändern, das Tausende, Millionen, Milliarden haben könnte. Millionen von Einträgen, anstatt nur die Logik im Code zu ändern: Nur der Teil, der es einer Person nicht ermöglichte, sowohl als Student als auch als Angestellter registriert zu werden.
(Es ist sehr unwahrscheinlich, aber mir fällt gerade nichts anderes ein. Anscheinend ist es möglich).
Warum interessieren uns Geschäftsregeln im Datenbankdesign und nicht im Code?
# 1: Eine Notiz 7 Jahre später, ein Beispiel aus dem wirklichen Leben:
Ich habe eine Regierung gesehen, in der aufgrund eines Fehlers ausgegebene SSNs dupliziert wurden: mehrere Personen, dieselbe SSN. Diejenigen, die die ursprüngliche Datenbank entworfen haben, haben definitiv den Fehler begangen, diese Eindeutigkeitsbeschränkung nicht in der Datenbank anzuwenden. (und später ein Fehler in der Originalanwendung? Mehrere Anwendungen, die die gemeinsam genutzte Datenbank verwenden und sich nicht einig sind, wo die Einschränkung abgelegt, überprüft und durchgesetzt werden soll? ...).
Dieser Fehler wird noch viele Jahre im System und in dem gesamten System weiterleben, das danach entwickelt wurde, und auf die Datenbank des ursprünglichen Systems angewiesen sein. Als ich die Antworten hier las, lernte ich, alle Einschränkungen, so viele wie möglich, weise (nicht blind) in der Datenbank anzuwenden, um die reale physische Welt dort draußen so gut wie möglich darzustellen.
quelle
Antworten:
Einige Einschränkungen lassen sich am besten in der Datenbank und andere in der Anwendung durchsetzen.
Einschränkungen, die in der Datenbank am besten durchgesetzt werden, sind normalerweise vorhanden, da sie für die Struktur des Datenmodells von grundlegender Bedeutung sind, z. B. eine Fremdschlüssel-Einschränkung, um sicherzustellen, dass ein Produkt gültig ist
category_id
.Einschränkungen, die in einer Anwendung erzwungen werden, sind möglicherweise nicht grundlegend für das Datenmodell, z. B. müssen alle FooBar-Produkte blau sein. Später entscheidet möglicherweise jemand, dass FooBars auch gelb sein kann. Dies ist eine Anwendungslogik, die nicht unbedingt in der Datenbank vorhanden sein muss, obwohl Sie eine separate
colours
Tabelle erstellen können und die Datenbank verlangen kann, dass das Produkt auf einen gültigen Eintrag aus dieser Tabelle verweist. ABER die Entscheidung, dass der einzige Datensatzcolours
den Wert hat,blue
würde immer noch von irgendwo außerhalb der Datenbank kommen.Überlegen Sie, was passieren würde, wenn Sie keine Einschränkungen in der Datenbank hätten und alle in der Anwendung erzwingen müssten. Was würde passieren, wenn Sie mehr als eine Anwendung hätten, die mit den Daten arbeiten müsste? Wie würden Ihre Daten aussehen, wenn sich die verschiedenen Anwendungen dafür entscheiden, Beschränkungen unterschiedlich durchzusetzen?
Ihr Beispiel zeigt eine Situation, in der es möglicherweise günstiger war, die Einschränkung in der Anwendung und nicht in der Datenbank zu haben, aber vielleicht gab es ein grundlegendes Problem, wenn das ursprüngliche Datenmodell zu restriktiv und unflexibel war?
quelle
teachers_as_students
anderen Untertyp hatStudents
und auf die ein neuer Fremdschlüssel verweistTeachers
, und einen systemgenerierten Primärschlüssel anstelle eines sozialen Schlüssels Sicherheitsnummer. Auf diese Weise ist ein "Schüler" eigentlich ein Pseudonym für einen Lehrer, so dass sich der Lehrer trotzdem für den Unterricht anmelden kann. Es ist schwer zu sagen, wie gut dies funktionieren würde, ohne das gesamte Datenmodell zu sehen.color_products
und erstellen ,color
können Sie die zusätzlichen Dropdowns wahrscheinlich einfacher erstellen - die meisten IDEs / Schemalader unterstützen die folgenden fkeys.Weil:
Nur einige Gründe, die mir wichtig sind.
quelle
Die Daten werden den Anwendungscode wahrscheinlich noch lange überleben. Wenn die Regel für die Daten von entscheidender Bedeutung ist (z. B. Fremdschlüsseleinschränkungen, die die Integrität der Daten gewährleisten), muss sie in der Datenbank vorhanden sein. Andernfalls besteht die Gefahr, dass Sie die Einschränkung in einer neuen Anwendung verlieren, die auf die Datenbank zugreift. Mehrere Anwendungen treffen nicht nur auf Datenbanken (einschließlich einiger, die möglicherweise nicht erkennen, dass es eine wichtige Datenregel gibt), sondern einige von ihnen, z. B. Datenimport- oder Berichtsanwendungen, können möglicherweise die in der Hauptdateneingabeanwendung eingerichtete Datenschicht nicht verwenden. Ehrlich gesagt ist die Wahrscheinlichkeit, dass ein Fehler in der Einschränkung auftritt, meiner Erfahrung nach im Anwendungscode viel höher.
Meiner persönlichen Meinung nach (basierend auf über 30 Jahren Umgang mit Daten und Erfahrung mit Hunderten verschiedener Datenbanken, die für viele verschiedene Zwecke verwendet werden), wird jeder, der die Beschränkungen nicht in die Datenbank einsetzt, in die er gehört, irgendwann schlechte Daten haben. Manchmal können schlechte Daten unbrauchbar werden. Dies gilt insbesondere dann, wenn Sie über finanzielle / aufsichtsrechtliche Daten verfügen, die bestimmte Kriterien für die Prüfung erfüllen müssen.
quelle
Die meisten Einschränkungen der referenziellen Integrität, die außerhalb der Datenbank implementiert werden, können aufgehoben werden. Wenn Sie also möchten, dass Ihre Daten jederzeit eine garantierte Integrität aufweisen, müssen Sie Einschränkungen in der Datenbank anwenden. Punkt, das war's.
Normalerweise werden Einschränkungen auf Anwendungsebene durch den Konsistenzmechanismus für Datenbanklesevorgänge beseitigt, mit dem Sitzungen die Daten anderer Sitzungen erst dann anzeigen können, wenn sie festgeschrieben wurden.
Beispielsweise können zwei Sitzungen versuchen, denselben Wert in eine Spalte einzufügen, die eindeutig sein soll. Sie können sowohl Scheck zur gleichen Zeit , dass der Wert nicht bereits existiert, können sowohl Einsatz ihren Wert, und können sowohl begehen. Eine in der Datenbank implementierte eindeutige Einschränkung würde dies nicht zulassen.
Dies ist den Entwicklern von Anwendungssprachen übrigens nicht unbekannt. Lesen Sie Abschnitt 3.10 Einzigartigkeit in den Ruby on Rails-Handbüchern: Active Record Validations and Callbacks
quelle
Vorteile der von der Datenbank erzwungenen Einschränkungen:
Einfachheit - Das Deklarieren einer Einschränkung ist wesentlich einfacher als das Deklarieren einer Einschränkung und das Schreiben des Codes, der diese Deklaration erzwingt.
Genauigkeit - Code, den Sie nicht geschrieben haben, weist niemals einen von Ihnen erstellten Fehler auf. Datenbankanbieter verbringen viel Zeit damit, sicherzustellen, dass ihr Einschränkungscode korrekt ist, sodass dies nicht erforderlich ist.
Geschwindigkeit - Ihre Anwendung kann niemals mehr Verteilungen haben als die Datenbank, auf der sie basiert. Datenbankanbieter verbringen viel Zeit damit, sicherzustellen, dass ihr Einschränkungscode effizient ist, sodass dies nicht erforderlich ist. Die Datenbank selbst hat auch einen schnelleren Zugriff auf die Daten, als eine Anwendung jemals haben könnte, egal wie effizient.
Wiederverwendung - Sie können mit einer Anwendung auf einer Plattform beginnen, dies kann jedoch nicht der Fall sein. Was ist, wenn Sie über ein anderes Betriebssystem, eine andere Hardware oder eine Sprachschnittstelle auf die Daten zugreifen müssen? Aufgrund von Einschränkungen in der Datenbank muss dieser Code niemals für die neue Plattform neu geschrieben werden und es muss niemals ein Fehlerbehebungsverfahren durchgeführt oder ein Profil für die Geschwindigkeit erstellt werden.
Vollständigkeit - Anwendungen erzwingen Einschränkungen, wenn Daten in die Datenbank eingegeben werden, und erfordern zusätzlichen Aufwand, um die Richtigkeit älterer Daten zu überprüfen oder Daten zu manipulieren, die sich bereits in der Datenbank befinden.
Langlebigkeit - Ihre Datenbankplattform überlebt wahrscheinlich eine bestimmte Anwendung.
quelle
Warum werden Einschränkungen auf dem Server angewendet? Weil Sie die Bösen nicht zwingen können, Ihren Klienten zu benutzen.
Zur Verdeutlichung: Wenn Sie in Ihrer Client-Anwendung nur Geschäftsregeln verarbeiten, kann eine andere Person mit einem anderen Tool eine Verbindung zum Datenbankserver herstellen und alle gewünschten Aktionen ausführen, ohne von Ihren Geschäftsregeln und Integritätsprüfungen eingeschränkt zu werden. Es ist sehr schwierig, jemanden davon abzuhalten, ein beliebiges Tool irgendwo im Netzwerk zu verwenden.
Wenn Sie die Integritätsprüfung auf dem Datenbankserver durchführen, wird jeder Versuch, unabhängig vom Tool auf Daten zuzugreifen, durch Ihre Regeln eingeschränkt.
quelle
Einige gute Antworten hier und auf die Gefahr, andere Gedanken zu wiederholen:
UPDATE
Anweisung direkt für die Datenbank ausführe , wie verhindert Ihre Anwendung eine ungültige Änderung? Ein weiteres Problem mit Geschäftsregeln in der App besteht darin, dass das erneute Kompilieren / Bereitstellen schwierig sein kann, insbesondere bei verteilten Apps, bei denen möglicherweise nicht jeder gleichzeitig das Update erhält. Und schließlich hat das Ändern der Geschäftsregeln in der Anwendung keinerlei Auswirkungen auf bereits vorhandene Daten, die gegen die neuen Regeln verstoßen. Wenn Sie den Daten die neue Einschränkung hinzufügen, müssen Sie die Daten korrigieren.Wenn Sie explizit erwähnen, dass Sie plötzlich etwas zulassen, was vorher nicht zulässig war, ist dies kein wirkliches Problem. Sie entfernen die erzwungenen Einschränkungen, unabhängig davon, wo diese bestehen. Im umgekehrten Fall, wenn Lehrer plötzlich keine Schüler mehr sein dürfen, müssen Sie möglicherweise eine Reihe von Daten bereinigen, unabhängig davon, wo die Einschränkung zuvor bestand.
quelle
Die Datenbank kann Einschränkungen effektiv überprüfen. Besser als Code.
Integritätsbeschränkungen helfen der Datenbank, einen effektiven Ausführungsplan zu finden
Anwendung sieht lesekonsistente Ansicht, daher kann es kaum Eindeutigkeit garantieren. Während die Datenbank auch nicht festgeschriebene Daten sehen kann.
quelle
Kurze Antwort ... um die Datenintegrität (dh Genauigkeit und Gültigkeit) zu wahren.
Eine Ausnahme ...
Wenn die Datenbank nur die Daten einer einzelnen Anwendung für einen einzelnen Benutzer speichert, wie in den meisten Sqlite-Datenbanken, sind möglicherweise keine Einschränkungen erforderlich. Tatsächlich tun sie dies normalerweise nicht, um die Zugriffszeit so schnell zu halten, dass sie nicht messbar ist.
Für alles andere ...
Datenbanken dienen immer zwei Mastern, die ich Editoren und Benutzer nennen werde .
Die Redakteure speichern meistens Daten in der Datenbank und rufen jeweils einen oder eine geringe Anzahl von Datensätzen ab. Ihr Hauptanliegen ist der schnelle und genaue Zugriff auf alle zugehörigen Daten und die schnelle und zuverlässige Speicherung ihrer Änderungen.
Benutzer rufen meistens Daten ab und sind am meisten mit dem schnellen Zugriff auf unbestreitbar genaue Informationen befasst. Sie benötigen oft verschiedene Zählungen, Aggregationen und Auflistungen, die früher in diesen ikonischen, fußdicken Stapeln von Greenbar-Papier-Ausdrucken generiert wurden, heute aber normalerweise auf Webseiten landen.
Datenbankentwicklungsprojekte werden fast immer im Auftrag von Benutzern gestartet , aber das Design richtet sich nach den Dateneingabe- und Datensatzanforderungen der Editoren . Als solche reagieren unerfahrene Entwickler häufig auf das unmittelbare Bedürfnis nach Schnelligkeit (hauptsächlich der Entwicklung ), indem sie keine Einschränkungen in die Datenbank aufnehmen.
Wenn eine und nur eine Anwendung jemals Änderungen für die auf die Daten gehen werden verwendet, um ganze Leben der Datenbank und die Anwendung von einem oder einer kleinen Anzahl von gut koordiniert Individuen entwickelt wird, dann ist es vielleicht sinnvoll sein , vertrauen die Anwendung zur Gewährleistung der Datenintegrität.
Solange wir jedoch so tun, als könnten wir die Zukunft vorhersagen, können wir dies nicht.
Der Aufwand, eine Datenbank zu erstellen, ist zu hoch, um sie jemals wegzuwerfen. Wie ein Haus wird die Datenbank viele Male erweitert, geändert und renoviert. Selbst wenn es vollständig ersetzt wird, werden alle Daten in die neue Datenbank migriert, wobei alle alten Geschäftsregeln und -beziehungen erhalten bleiben.
Einschränkungen implementieren diese Regeln und Beziehungen in einer übersichtlichen, deklarativen Form in der Datenbank-Engine selbst, auf die problemlos zugegriffen werden kann. Ohne sie müssten nachfolgende Entwickler die Anwendungsprogramme durcharbeiten, um diese Regeln rückgängig zu machen. Viel Glück!
Dies ist übrigens genau das, was COBOL-Programmierer von Mainframes zu tun haben, da diese massiven Datenbanken häufig erstellt wurden, bevor es relationale Engines und Einschränkungen gab. Selbst wenn auf ein modernes System wie IBMs DB2 migriert wird, werden Einschränkungen manchmal nicht vollständig implementiert, da die Logik der alten Regeln, die möglicherweise in einer Reihe von COBOL- "Batch" -Programmen enthalten sind, so kompliziert sein kann, dass sie nicht praktisch zu konvertieren sind. Stattdessen können automatisierte Tools verwendet werden, um das alte COBOL in eine neuere Version mit Schnittstellen zur neuen relationalen Engine umzuwandeln. Mit ein wenig Optimierungsaufwand bleibt die Datenintegrität erhalten ... bis eine neue App geschrieben wird, die alles auf subtile Weise beschädigt und das Unternehmen geschleppt wird vor Gericht, um beispielsweise Tausende von Hausbesitzern, die sie nicht haben sollten, auszuschließen.
quelle
Neben den anderen Kommentaren ...
Wenn Sie eine Datenbank haben, in der eine Tabelle von einer oder mehreren Anwendungen oder Codepfaden aktualisiert werden kann, bedeutet das Platzieren der entsprechenden Einschränkungen in der Datenbank, dass Ihre Anwendungen nicht den gleichen Einschränkungscode duplizieren. Dies kommt Ihnen zugute, indem Sie die Wartung vereinfachen (indem Sie die Anzahl der zu ändernden Stellen reduzieren, wenn sich das Datenmodell ändert) und sicherstellen, dass die Einschränkungen unabhängig von der Anwendung, mit der die Daten aktualisiert werden, konsistent angewendet werden.
quelle
Persönlich ist es meiner Meinung nach einfacher, Einschränkungen zu erstellen und zu ändern, als beispielsweise Trigger zu erstellen. Dies wäre eine Möglichkeit, Ihre Geschäftsregel mithilfe von Quellcode durchzusetzen.
Es ist auch weniger wahrscheinlich, dass Trigger portierbar sind, da sie normalerweise in herstellerspezifischen Sprachen wie PL / SQL geschrieben sind.
Wenn jedoch Einschränkungen nicht Ihren Anforderungen entsprechen, können Sie immer Trigger verwenden, um Ihre Geschäftsregeln durchzusetzen.
quelle
Sie sollten immer in der Datenbank angewendet werden zuerst da,
varchar(5)
Typ haben, besteht eine gute Chance, dass Sie ein Schema finden, das ORM für Ihre spezifische Sprache lädt, das den Sprachtyp dem Typ des Schemas zuordnet und dessen eigene Größenbeschränkung zusammenstellt.DBIx for Perl is one such schema loader
; Hier ist eine andere für das Entity Framework . Die Fähigkeiten dieser Loader variieren, aber alles, was sie bieten können, ist ein guter Anfang, um die Integrität der App sicherzustellen, ohne die Datenbank zu verlassen.quelle