13 Stimmen

Datenbankschema, das spezielle Eigenschaften unterstützen kann

Ich muss eine Reihe von Entitäten speichern, von denen es mehrere spezielle Versionen gibt. Sie haben einige gemeinsame Eigenschaften, aber die spezialisierten Versionen enthalten spezifische Eigenschaften für diese Entität.

Lösungen

Der Datenspeicher ist ein relationales DBMS, und das steht nicht zur Diskussion :-) Genauer gesagt handelt es sich um den Microsoft SQL Server 2005.

Ich könnte leicht eine Tabelle für die allgemeinen Eigenschaften und dann eine Tabelle für jede der speziellen Versionen erstellen. Es ist jedoch wahrscheinlich, dass der Lösung später neue Entitäten hinzugefügt werden müssen, und ich möchte nicht sowohl ein Objektmodell y ein Datenbankschema.

Eine weitere Die Idee ist, eine Tabelle zu erstellen

reading(<common properties>, extended_properties)

und haben die extended_properties Feld eine Art der Serialisierung der erweiterten Eigenschaften sein. Ich war entweder JSON oder XML denken. Ich werde höchstwahrscheinlich ein ORM-Framework verwenden, aber ich habe noch nicht entschieden. So oder so, die Objektdarstellung einer spezialisierten Entität aus dem reading könnte ein Wörterbuch aufdecken {extended_property_name, value} mit den geparsten Schlüssel/Wertpaaren aus der Datei extended_properties Feld.

Von diesem http://msdn.microsoft.com/en-us/library/ms345117(SQL.90).aspx Ich gehe davon aus, dass XML-Felder in Verbindung mit Schemata für diese Felder die Vorstellung von typisiertem XML innerhalb des DBMS vermitteln. Außerdem können Abfragen, die den XML-Inhalt in der extended_properties können diese ebenfalls berücksichtigt werden.

Was ich will

Feedback zu meinen Lösungsvorschlägen, vor allem zu dem mit dem reading Tabelle und Serialisierung der erweiterten Eigenschaften.

Mir ist auch klar, dass dies eine der Einschränkungen von relationalen DBMS im Vergleich zu schlüssel-/wertbasierten Speichern ist. Es muss jedoch sicherlich einige Modellierungstechniken geben, um dies zu berücksichtigen.

Wir sind für jedes Feedback dankbar!

19voto

PerformanceDBA Punkte 29854

Anders, geben Sie nicht auf jede Integrität oder Härte, zB Typ Sicherheit.

(Antwort folgt).

@Anders. Nein, ganz und gar nicht, Subtypisierung ist in Ordnung (die Frage ist, welche Form Sie verwenden und was die Nachteile sind). Geben Sie keine Stärke oder Integrität oder Typsicherheit oder Prüfungen oder DRI auf. Die von Ihnen gewählte Form erfordert zusätzliche Prüfungen und vielleicht ein wenig Code (hängt von Ihrer Plattform ab).

Dieses Thema kommt häufig zur Sprache, aber der Suchende hat immer eine eingeschränkte Perspektive; ich mache immer wieder die gleichen Aussagen (eine Teilmenge) aus einer unveränderlichen Menge. Es geht darum, alle Optionen zu bewerten. Also schreibe ich ein Dokument. Leider dauert es länger. Vielleicht 4 Seiten. Noch nicht fertig zum Posten. Aber die Diagramme sind fertig, ich denke, Sie sind am Ball, und Sie können es sofort verwenden.

Warnung: Nur erfahrene Projektbauingenieure
Straße nicht geeignet für Wohnwagen oder Leser mit hohem Eek-Faktor

Link zu Vier alternative Datenmodelle in Dokument im Aufbau. Ich entschuldige mich für die Unordnung auf dem Boden; ich werde bald aufräumen.

Link zur IDEF1X-Notation für alle, die mit dem Standard für die Modellierung relationaler Datenbanken nicht vertraut sind.

  1. Sie sind alle relational, mit voller Integrität.

  2. Die 6NF-Optionen. Relational heute (SQL) bietet keine Unterstützung für 6NF; es verbietet es nicht, es bietet nur nicht die 5NF6NF Strukturen. Daher müssen Sie einen kleinen Katalog erstellen, den manche als "Metadaten" bezeichnen. Dabei handelt es sich eigentlich nur um eine Erweiterung des Standard-SQL-Katalogs (sys-Tabellen). Der erforderliche Grad der Kontrolle wird in jeder Option modelliert.

  3. Im Grunde ist EAV richtig gemacht, mit voller Kontrolle und Integrität (Typsicherheit, deklarative referentielle Integrität usw.) und nicht das übliche Chaos.

Diese Fragen/Antworten könnten für Sie von Interesse sein (siehe insbesondere die Datenmodelle):

Mehrfach fest vs. abstrakt flexibel

Datenbankschema-bezogenes Problem

"Einfaches" Datenbankentwurfsproblem

Antwort auf Kommentare

... Auf diese Weise können wir leicht "Kommentar"-Zeilen erfassen, die mit einer bestimmten spezialisierten Typinstanz verbunden sind. Ist dies der richtige Weg, oder werde ich diese Entscheidung später bereuen? Gibt es ein anderes Muster, das wir übersehen?

Ich bin nicht sicher, was Sie meinen. Kommentare, Notizen, Adressen werden am Ende in vielen Tabellen verwendet (Spalten in), so dass die richtige Methode ist, sie zu normalisieren; bieten Sie eine Tabelle für Kommentar, die von jeder Tabelle, die es erfordert referenziert wird. Hier ist eine allgemeine Tabelle für Kommentare. Sie wird in Product (dem Supertyp) verwendet, weil Sie angegeben haben jede Produkt. Es kann genauso gut in einigen der Produkt-Subtypen verwendet werden und in anderen nicht; in diesem Fall wird die FK in diesen Produkt-Subtypen sein.

Ihr Datenmodell

Welchen Zweck erfüllt die Tabelle ProductType in Ihrem Beispiel Product 5NF/subtype? Enthält sie eine Zeile für jedes spezialisierte Produkt, z. B. ProductCPU? Ich nehme an, sie gibt an, welche Spezialisierung das Basisprodukt ist.

(Kleiner kritischer Fehler im Diagramm, korrigiert.)

Ja, genau.

In der relationalen Standardsprache (nicht in dem unkontrollierten Durcheinander, das sich als Datenbank ausgibt) ist der ProductType die Diskriminierungsmerkmal Sie gibt an, welche der Produktuntertypen auf dieses Produkt zutreffen. Sagt Ihnen, mit welcher Produktuntertyp-Tabelle Sie sich verbinden müssen. Beide zusammen ergeben ein logisches Produkt. Vergessen Sie nicht, die Views zu erstellen, eine für jeden ProductType.

  • (Bewerten Sie für jedes der vier Datenmodelle, wie sich ProductType ändert und welche Rolle es genau spielt).

  • "Generalisierung-Spezialisierung" ist alles Hokuspokus, OO-Terminologie; ohne die Grenze zu überschreiten und zu lernen, wozu Relational seit 30 Jahren fähig ist. Wenn Sie ein wenig über Relational lernen, werden Sie die volle Leistung haben; andernfalls sind Sie auf den sehr begrenzten OO-Ansatz für alles beschränkt (Ambler und Fowler haben eine Menge zu verantworten). Bitte lesen Sie diese Stelle , von 11 Dez 10 weiter. Relationale Datenbanken modellieren Entitäten, keine Objekte, keine Klassen.

Wenn Sie zum Beispiel ein neues Produkt hinzufügen, möchten Sie eine Dropdown-Auswahl der Produkttypen anbieten, die Sie hinzufügen können. Anhand dieser Auswahl lässt sich ableiten, in welche Tabellen die Daten eingegeben werden sollen. Ist das richtig? Es tut mir leid, dass ich über Anwendungscode spreche, aber ich muss es einfach in die richtige Perspektive setzen

Ja. Und welche Seite (mit Feldern) soll als nächstes bereitgestellt werden, damit der Benutzer Daten eingeben kann.

Es ist kein Problem, über den Anwendungscode zu sprechen, der die Rdb verwenden wird, sie gehören zusammen wie Mann und Frau (nicht wie Mann und Sklave).

  • Für Ihre OO-Klassen ordnen Sie den Klassenbaum der Rdb zu, sobald Sie die Modellierung der Rdb abgeschlossen haben, unabhängig von jeder Anwendung, die sie verwenden wird. Nicht andersherum. Und nicht abhängig von einer bestimmten Anwendung.

  • Vergessen Sie das "Persistieren", es bringt viele Probleme mit sich (verlorene Aktualisierungen; beschädigte Datenintegrität; problematische Fehlersuche; massive Konflikte; usw.). Alle Aktualisierungen der Rdb sollten in Transaktionen erfolgen, mit ACID-Konformität, die seit 30 Jahren verfügbar ist, aber Fowler und Ambler haben davon noch nichts gelesen. Normalerweise bedeutet das einen gespeicherten Proc vor xact.

Die Diskriminante ist eine FK zu einer Typ-Tabelle, wie wir bereits festgestellt haben. Sie gibt an, welche spez. Untertyp, an den sich der Basistyp hält. Doch was enthält die Diskriminantentabelle im Einzelnen?

Geht das nicht aus dem Datenmodell hervor? ProducType CHAR(1) o (2). Name Char(30) .

Es könnte ein anzeigefreundlicher Text sein, der den Typ für UI-Zwecke angibt,

Ja, u. a. zur Kontrolle, Einschränkung usw., zur Beseitigung von Mehrdeutigkeiten bei der Kodierung oder Berichterstattung.

aber enthält sie auch den genauen Tabellennamen, der den spezialisierten Typ enthält?

Nein. Das wäre ein bisschen zu physisch, um in Daten untergebracht zu werden. Aus Prinzip nicht erlaubt.

Aber das ist nicht notwendig.

Angenommen, ich interessiere mich für das Produkt mit ID = 1. Es hat eine Diskriminante, die anzeigt, dass es ein ProductCPU ist. Wie würden Sie vorgehen, um diese ProductCPU aus Ihrem Anwendungscode abzurufen?

Das wird einfach sein, wenn Sie das bereitgestellte Modell nehmen und es (alle Tabellen) als Klassen, korrekt, etc. implementieren. Das von Ihnen angefragte Beispiel verwendet keine Views (die für Listen und allgemeinere Verwendung gedacht sind). Der Pseudo-Code würde sein:

  • in Anbetracht der ProductId (Untertyp unbekannt, daher sollten Sie nicht in einem Untertyp-spezifischen Fenster sitzen), laden Sie die Product nur Supertyp

  • basierend auf dem Discriminator Product.ProductType setzen, Indikatoren setzen usw. und den entsprechenden Subtyp laden, einen von ProductCPU; ProductMemory; ProductDisk; ProductTape ; usw.

  • Ich habe OO-Methoden gesehen (und bin damit nicht einverstanden), die alle Subtypen für den gegebenen ProductId auf einmal: ein Subtyp ist gültig, die anderen sind ungültig. Der Code muss sich noch auf die gültige Klasse für die Product auf Grund Product.ProductType .

Alternativ, z.B. wenn der Kontext ist, sitzt der Benutzer in einem Subtype-spezifischen Fenster, z.B. ProductCPU mit dieser eingestellten Klasse, und fordert ProductId xxx. Verwenden Sie dann die ProductCPU Ansicht. Wenn sie null Zeilen zurückgibt, existiert sie nicht.

  • Möglicherweise gibt es eine ProductDisk xxx, aber nicht ein ProductCPU xxx. Wie man damit umgeht, ob man angibt, dass es ein Product`xxx gibt, es aber keine CPU ist, oder nicht, hängt von den Anforderungen der App ab.

Für Listen, bei denen die App ein Raster ausfüllt, ohne Rücksicht auf die ProductId Verwenden Sie die Ansichten (jeweils eine), um jedes Gitter zu laden. Dieses SQL basiert auf der Verknüpfung und muss sich nicht auf ProductType .

1voto

p.marino Punkte 6166

Ich persönlich würde mich für die Methode "eine Tabelle für die allgemeinen Eigenschaften und dann eine Tabelle für jede der speziellen Versionen erstellen" entscheiden.

Grund: Sie sagen, dass Ihre Implementierung in einem RDBMS erfolgen wird und dies nicht verhandelbar ist. Nun gut. Dumping unstrukturiert, Blob-ähnliche Sachen wie eine serialisierte Hashtable in einem DB-Feld geht gegen die Design-Philosophie von RDBMS aber, so dass Sie einen schweren Schlag auf Effizienz haben, es sei denn, Sie sind in Ordnung mit der Idee der Behandlung der *extended_properties* Feld als ein undurchsichtiges Blob, genau wie ein gif oder ein anderes binäres Objekt.

Mit anderen Worten: Vergessen Sie die (effiziente) Abfrage nach "allen Objekten mit erweitertes Eigentum COLOR=RED".

Das Problem, das Sie haben (die Beschreibung von OO-Taxonomien in einem RDBMS) ist definitiv nicht neu. Werfen Sie einen Blick auf este für eine ausführliche Beschreibung der Optionen.

1voto

Walter Mitty Punkte 17177

Dies ist ein klassisches Beispiel für das gen-spec-Designmuster. Gen-spec wird in jedem Tutorium über Objektmodellierung behandelt, da es durch Vererbung gehandhabt wird. In Tutorien über relationale Datenmodellierung wird es häufig übersprungen. Aber es wird gut verstanden.

Suchen Sie im Internet nach "Generalisierung, Spezialisierung, relationale Modellierung". Sie werden mehrere Artikel darüber finden, wie Sie eine einzige Tabelle für die allgemeine Klasse und eine Tabelle für jede spezialisierte Klasse einrichten. Die Artikel helfen Ihnen bei der Erstellung von Fremdschlüsseln. Insbesondere erfüllt der Primärschlüssel jeder spezialisierten Tabelle eine doppelte Aufgabe. Er ist auch ein Fremdschlüssel für die allgemeine Tabelle.

Dies wird Ihnen nicht sehr vertraut vorkommen, wenn Sie an die Objektmodellierung gewöhnt sind. Aber Sie werden feststellen, dass es gut funktioniert. Und die Lösung, die in den meisten Artikeln angeboten wird, ist nicht dynamisch, so dass Sie jedes Mal, wenn eine neue spezialisierte Unterklasse entdeckt wird, etwas DDL machen müssen.

0voto

Damir Sudarevic Punkte 21527

Hier sind fünf Beispiele aus der SO. Welches Sie verwenden, hängt von der konkreten Problemstellung und Ihren Präferenzen ab.

Im Allgemeinen würde ich von der Serialisierung von Daten in DB-Felder abraten.

Wenn es relativ wenige spezialisierte Versionen einer Entität gibt, können Sie wie in diesen Beispielen einfach Subtypisierung verwenden: Beispiel eins , Beispiel zwei .

Für große Werte von Eigenschaften oder wenn die Eigenschaften dynamisch definiert werden sollen (keine Schemaänderungen), sollten Sie eine Implementierung des Beobachtungsmusters wie in diesen Beispielen in Betracht ziehen: Beispiel drei , Beispiel vier ; oder in die so genannte 6. Normalform, wie in beschrieben: Beispiel fünf . Beachten Sie, dass das "Beobachtungsmuster" eine vereinfachte Version der 6.

-1voto

JeffO Punkte 7827

Diese Technik kann einige Probleme mit dem richtigen Design und der Leistung haben, aber Sie scheinen einen Kompromiss mit Flexibilität zu brauchen.

Anstatt spezifische Tabellen oder sogar ein neues Feld für jede Eigenschaft zu erstellen, könnten Sie eine Tabelle (und die wird ziemlich groß sein) für eindeutige Eigenschaften haben:

Unique_Property_ID
, FK_To_Some_Entity (Not sure what entity these link to: customers, bills, etc.) 
, Property_Type Not the data type but a link to a table describing this entity)
, Property_Value (Difficult to determine if all of your values will be of the same type: string, int, date, etc.)

Beispiel: Ein Gebrauchtwagenhändler, der Zusatzausstattungen für verschiedene Marken und Modelle erfassen muss (er weiß nie, was er bekommen wird). Ein paar Datensätze könnten wie folgt aussehen:

VehicleID   Property Type  Property Value
3           Sound System   Bose
3           Hybrid System  Battery
7           Starter Type   Hand Crank
7           Passenger Seat Rumble
9           Starter Type   Kick Start
9           Passenger Seat Side Car

Jeder Wert für jeden Eigenschaftstyp Set | hätte seinen eigenen Datensatz.

Ein weiteres Problem ist, dass Sie die Tabelle transponieren müssen, wenn Sie jede Eigenschaft als Spalte darstellen wollen.

CodeJaeger.com

CodeJaeger ist eine Gemeinschaft für Programmierer, die täglich Hilfe erhalten..
Wir haben viele Inhalte, und Sie können auch Ihre eigenen Fragen stellen oder die Fragen anderer Leute lösen.

Powered by:

X