Eine neue Anforderung ist auf einer alten Codebasis aufgetaucht, die im Grunde eine direkte (interne) Kommunikation zwischen zwei zuvor nicht direkt verwandten Benutzerklassen ermöglicht (die in verschiedenen Tabellen mit völlig unterschiedlichen Schemata gespeichert sind, und leider ist der Code kaum OO-fähig, viel weniger entworfen, daher gibt es keine Elternklasse). Da wir eine Tasche an dieses alte Setup hängen möchten, das diese Funktionalität nie in Betracht gezogen hat, gibt es keine Garantie dafür, dass es keine PK-Kollisionen gibt - angesichts des verwendeten Datensatzes ist praktisch garantiert, dass es diese gibt.
Die Lösung scheint also offensichtlich: Töte es mit Feuer und schreibe das ganze Chaos neu. Eine Mapping-Tabelle. Ich habe zwei Anweisungen für die möglichen Implementierungsmethoden der Karte erhalten, bin jedoch kein DBA. Daher bin ich mir nicht sicher, ob ich Vor- und Nachteile verpasst habe.
Betrachten Sie zur Verdeutlichung der Abstraktion drei Gruppen unterschiedlicher Benutzerdaten: Professoren, Verwaltung, Studenten (Nein, dies ist keine Hausaufgabe. Versprechen!)
Zuordnung 1
(professor_id, admin_id und student_id sind Fremdschlüssel für ihre jeweiligen Tabellen)
| mailing_id (KEY) | professor_id | admin_id | student_id |
-------------------------------------------------------
| 1001 | NULL | 87 | NULL |
| 1002 | 123 | NULL | NULL |
| 1003 | NULL | NULL | 123 |
Die +/- zu diesem Ansatz scheinen ziemlich nachteilig zu sein:
- Zwei "verschwendete" Felder pro Zeile
- Verstößt gegen 2NF
- Anfällig für das Einfügen / Aktualisieren von Anomalien (eine Zeile mit nur 0-1 Feldsatz NULL, z.
Die Profis sind jedoch nicht ohne eigene Verdienste:
- Das Mapping kann mit einer einzigen Suche durchgeführt werden
- Bestimmen Sie einfach die "Quell" -Daten für einen bestimmten Benutzer aus der Mailing-ID
Um ehrlich zu sein, in meinem Bauch mag ich diese Idee überhaupt nicht.
Zuordnung 2
(Angenommen, MSG_ * sind definierte Konstanten, Aufzählungstypen oder ein anderer geeigneter Bezeichner.)
| mailing_id (KEY) | user_type (UNIQUE1) | internal_id (UNIQUE2)|
------------------------------------------------------------------
| 1001 | MSG_ADMIN | 87 |
| 1002 | MSG_PROF | 123 |
| 1003 | MSG_STUDENT | 123 |
Mit diesem Setup und einem eindeutigen zusammengesetzten Index von {user_type, internal_id} werden die Dinge viel sauberer, 3NF wird beibehalten und der Anwendungscode muss nicht nach E / A-Anomalien suchen.
Auf der anderen Seite gibt es einen gewissen Transparenzverlust bei der Bestimmung der Benutzerquellentabellen, die außerhalb der Datenbank verarbeitet werden müssen. Dies entspricht im Wesentlichen einer Zuordnung von Werten für den Benutzertyp zu Tabellen auf Anwendungsebene. Im Moment neige ich (ziemlich stark) zu dieser zweiten Abbildung, da der Nachteil eher gering ist.
ABER ich bin mir meiner eigenen Grenzen schmerzlich bewusst und bin mir sicher, dass ich wahrscheinlich Vorteile oder Stolpersteine in beide Richtungen verpasst habe, also wende ich mich klügeren Gedanken zu als meinen.
quelle
Antworten:
Ihre zweite Idee ist die richtige. Mit diesem Ansatz können Sie alle Zuordnungen vornehmen, die Sie zur Integration Ihrer drei kollidierenden Schlüsselbereiche benötigen.
Wichtig ist, dass die Datenbank den größten Teil der Konsistenz, die Sie benötigen, mithilfe deklarativer Einschränkungen auferlegt .
Sie haben bereits mehr Code als Sie möchten. Fügen Sie also nicht mehr Code hinzu, als unbedingt erforderlich ist, um Ihre integrierte Schlüsselliste konsistent zu halten. Lassen Sie Ihr Datenbankmodul das tun, wofür es entwickelt wurde.
Das "Sorgenkind", das Ihnen in Mapping 2 Unbehagen bereitet, ist die
USER_TYPE
Spalte. Diese Spalte ist wichtig, da Sie sie benötigen, um sicherzustellen, dassINTERNAL_ID
sie pro Benutzertyp höchstens einmal angezeigt wird. Das einzige Mal, wenn Sie Code benötigen, der überhaupt bekanntUSER_TYPE
ist, ist der Code, der in Ihre Zuordnungstabelle eingefügt und aus dieser gelöscht wird. Dies kann ziemlich gut lokalisiert werden. Ich würde davon ausgehen, dass Sie einen einzelnen Punkt in Ihrem Code erstellen, an dem der Inhalt der Zuordnungstabelle beibehalten wird. Eine zusätzliche Spalte an dieser einen Stelle, an der Daten geschrieben werden, ist keine große Sache. Was Sie wirklich vermeiden möchten, ist das Hinzufügen der zusätzlichen Spalte überall dort, wo die Daten gelesen werden .Der Code in Ihren Unteranwendungen, der die Zuordnung verwenden muss, kann das
USER_TYPE
einfach ignorieren, indem Sie jeder Unteranwendung eine Ansicht geben, die die Zuordnungen auf den einen anwendungsspezifischen Benutzertyp herunterfiltert.quelle
Aus Erfahrung empfehle ich, Konsistenz gegenüber Eleganz oder „Best Practice“ zu wählen. Dies entspricht dem vorhandenen Design und DREI Mailing-Tabellen (eine für jede Rolle) mit einer einfachen
mailing_id, user_id
Feldstruktur.Es ist unelegant, hat aber einige Vorteile ...
Ich bin sicher, dass viele andere mit diesem Ansatz nicht einverstanden sind, aber das Hauptziel der Normalisierung und der Best Practices besteht darin, den Code konsistenter zu machen, damit er leichter zu befolgen und zu debuggen ist ... und es ist wahrscheinlich nicht möglich, die gesamte Codebasis auf den neuesten Stand zu bringen.
quelle