Wie modelliere ich einen Entitätstyp, der verschiedene Sätze von Attributen haben kann?


11

Ich habe Probleme beim Neuerstellen einer Datenbank mit einer Eins-zu-Viele-Beziehung (1: M) zwischen Benutzern und Elementen .

Das ist ziemlich einfach, ja; Jeder Gegenstand gehört jedoch zu einer bestimmten Kategorie (z. B. einem Auto , einem Boot oder einem Flugzeug ), und jede Kategorie weist eine bestimmte Anzahl von Attributen auf, z.

Car Struktur:

+----+--------------+--------------+
| PK | Attribute #1 | Attribute #2 |
+----+--------------+--------------+

Boat Struktur:

+----+--------------+--------------+--------------+
| PK | Attribute #1 | Attribute #2 | Attribute #3 |
+----+--------------+--------------+--------------+

Plane Struktur:

+----+--------------+--------------+--------------+--------------+
| PK | Attribute #1 | Attribute #2 | Attribute #3 | Attribute #4 |
+----+--------------+--------------+--------------+--------------+

Aufgrund dieser unterschiedlichen Anzahl von Attributen (Spalten) hielt ich es zunächst für eine gute Idee, für jede Kategorie eine separate Tabelle zu erstellen , um mehrere NULL-Werte zu vermeiden und die Indizierung besser zu nutzen.

Obwohl es auf den ersten Blick großartig aussah, konnte ich keinen Weg finden, die Beziehung zwischen dem Elementen und den Kategorien über die Datenbank herzustellen, da ich zumindest in meiner bescheidenen Erfahrung als Datenbankadministrator beim Erstellen von Fremdschlüsseln explizit eine Datenbank informiere den Tabellennamen und die Spalte.

Am Ende möchte ich eine solide Struktur, um alle Daten zu speichern und gleichzeitig alle Mittel zu haben, um alle Attribute von allen aufzulisten Elemente aufzulisten, die ein Benutzer möglicherweise mit einer Abfrage hat.

Ich könnte dynamische Abfragen fest codieren mit der serverseitigen Sprache fest , aber ich halte dies für falsch und nicht sehr optimal.

Zusätzliche Information

Dies sind meine Antworten auf MDCCL-Kommentare:

1. Wie viele Artikelkategorien von Interesse gibt es in Ihrem Geschäftskontext, drei (dh Autos , Boote und Flugzeuge) ) oder mehr?

Tatsächlich ist es sehr einfach: Insgesamt gibt es nur fünf Kategorien .

2. Gehört derselbe Artikel immer demselben Benutzer ( dh wenn ein bestimmter Artikel einem bestimmten Benutzer „zugewiesen“ wurde, kann er nicht mehr geändert werden)?

Nein, sie könnten sich ändern. Im fiktiven Szenario der Frage wäre es so, als würde Benutzer A Artikel 1 für Benutzer B verkaufen , daher muss das Eigentum reflektiert werden.

3. Gibt es Attribute, die von einigen oder allen Kategorien gemeinsam genutzt werden ?

Nicht geteilt, aber aus dem Speicher kann ich erkennen, dass in allen Kategorien mindestens drei Attribute vorhanden sind .

4. Besteht die Möglichkeit, dass die Kardinalität der Beziehung zwischen Benutzer und Gegenstand viele zu viele (M: N) anstelle von eins zu vielen (1: M) ist? Zum Beispiel bei folgenden Geschäftsregeln: A User owns zero-one-or-many ItemsundAn Item is owned by one-to-many Users

Nein, da Gegenstände ein physisches Objekt beschreiben würden. Benutzer erhalten eine virtuelle Kopie davon, die jeweils durch eine eindeutige GUID v4 gekennzeichnet ist

5. Zu Ihrer folgenden Antwort auf einen der Fragenkommentare:

"Im fiktiven Szenario der Frage wäre es so, als würde Benutzer A Artikel 1 für Benutzer B verkaufen , daher muss das Eigentum reflektiert werden."

Es scheint, dass Sie planen , sozusagen die Entwicklung des Artikelbesitzes zu verfolgen . Welche Attribute möchten Sie auf diese Weise über ein solches Phänomen speichern? Nur die Änderung des Attributs, die den bestimmten Benutzer angibt , der Eigentümer eines bestimmten Elements ist ?

Nein nicht wirklich. Das Eigentum kann sich ändern, aber ich brauche keine Spur von der vorherigen zu halten Eigentümer .

Antworten:


18

Entsprechend Ihrer Beschreibung des betrachteten Geschäftsumfelds gibt es eine Supertyp-Subtyp- Struktur, die Item - den Supertyp - und jede seiner Kategorien , dh Auto , Boot, umfasst und Flugzeug (zusammen mit zwei weiteren, die nicht bekannt gegeben wurden). die Untertypen -.

Ich werde im Folgenden detailliert auf die Methode eingehen, mit der ich ein solches Szenario verwalten würde.

Geschäftsregeln

Um mit der Abgrenzung des relevanten konzeptionellen Schemas zu beginnen, können einige der wichtigsten bisher festgelegten Geschäftsregeln (Beschränkung der Analyse auf die drei offenbarten Kategorien , um die Dinge so kurz wie möglich zu halten) wie folgt formuliert werden:

  • Ein Benutzer besitzt null, eins oder viele Gegenstände
  • Ein Artikel gehört zu einem bestimmten Zeitpunkt genau einem Benutzer
  • Ein Artikel kann zu unterschiedlichen Zeitpunkten Eigentum von einem bis vielen Benutzern sein
  • Ein Artikel wird nach genau einer Kategorie klassifiziert
  • Ein Gegenstand ist zu jeder Zeit
    • entweder ein Auto
    • oder ein Boot
    • oder ein Flugzeug

Illustratives IDEF1X-Diagramm

Abbildung 1 zeigt ein IDEF1X 1- Diagramm, das ich erstellt habe, um die vorherigen Formulierungen zusammen mit anderen Geschäftsregeln zu gruppieren, die relevant erscheinen:

Abbildung 1 - Struktur des Supertyp-Subtyps für Elemente und Kategorien

Supertyp

Einerseits zeigt Item , der Supertyp, die Eigenschaften oder Attribute an, die allen Kategorien gemeinsam sind , d. H.

  • CategoryCode - angegeben als FOREIGN KEY (FK), der auf Category.CategoryCode verweist und als Subtyp- Diskriminator fungiert , dh die genaue Kategorie des Subtyps angibt, mit dem ein bestimmtes Element verbunden werden muss -,
  • OwnerId - wird als FK unterschieden, das auf User.UserId verweist , aber ich habe ihm einen Rollennamen 2 zugewiesen , um seine besonderen Auswirkungen genauer wiederzugeben -.
  • Foo ,
  • Bar ,
  • Baz und
  • CreatedDateTime .

Untertypen

Auf der anderen Seite die Eigenschaften , die sich auf jede bestimmte Kategorie beziehen , dh

  • Qux und Corge ;
  • Grault , Garply und Plugh ;
  • Xyzzy , Thud , Wibble und Flob ;

werden im entsprechenden Subtypfeld angezeigt.

Kennungen

Dann hat der Item.ItemId PRIMARY KEY (PK) 3 zu den Untertypen mit unterschiedlichen Rollennamen migriert , d. H.

  • CarId ,
  • BoatId und
  • FlugzeugId .

Sich gegenseitig ausschließende Assoziationen

Wie dargestellt, besteht eine Assoziation oder Beziehung der Kardinalität eins zu eins (1: 1) zwischen (a) jedem Auftreten eines Supertyps und (b) seiner komplementären Subtypinstanz.

Das exklusive Subtypsymbol zeigt die Tatsache an, dass sich die Subtypen gegenseitig ausschließen, dh ein konkretes Vorkommen von Gegenständen kann nur durch eine einzelne Subtypinstanz ergänzt werden: entweder ein Auto oder ein Flugzeug oder ein Boot (niemals durch zwei oder mehr).

, Ich habe klassische Platzhalternamen verwendet, um einige der Entitätstyp-Eigenschaften zu berechtigen, da ihre tatsächlichen Bezeichnungen in der Frage nicht angegeben wurden.

Layout auf logischer Ebene des Expositorys

Um ein logisches Expository-Design zu diskutieren, habe ich die folgenden SQL-DDL-Anweisungen basierend auf dem oben angezeigten und beschriebenen IDEF1X-Diagramm abgeleitet:

-- You should determine which are the most fitting 
-- data types and sizes for all your table columns 
-- depending on your business context characteristics.

-- Also, you should make accurate tests to define the 
-- most convenient INDEX strategies based on the exact 
-- data manipulation tendencies of your business context.

-- As one would expect, you are free to utilize 
-- your preferred (or required) naming conventions. 

CREATE TABLE UserProfile (
    UserId          INT      NOT NULL,
    FirstName       CHAR(30) NOT NULL,
    LastName        CHAR(30) NOT NULL,
    BirthDate       DATE     NOT NULL,
    GenderCode      CHAR(3)  NOT NULL,
    Username        CHAR(20) NOT NULL,
    CreatedDateTime DATETIME NOT NULL,
    --
    CONSTRAINT UserProfile_PK  PRIMARY KEY (UserId),
    CONSTRAINT UserProfile_AK1 UNIQUE ( -- Composite ALTERNATE KEY.
        FirstName,
        LastName,
        GenderCode,
        BirthDate
    ),
    CONSTRAINT UserProfile_AK2 UNIQUE (Username) -- ALTERNATE KEY.
);

CREATE TABLE Category (
    CategoryCode     CHAR(1)  NOT NULL, -- Meant to contain meaningful, short and stable values, e.g.; 'C' for 'Car'; 'B' for 'Boat'; 'P' for 'Plane'.
    Name             CHAR(30) NOT NULL,
    --
    CONSTRAINT Category_PK PRIMARY KEY (CategoryCode),
    CONSTRAINT Category_AK UNIQUE      (Name) -- ALTERNATE KEY.
);

CREATE TABLE Item ( -- Stands for the supertype.
    ItemId           INT      NOT NULL,
    OwnerId          INT      NOT NULL,
    CategoryCode     CHAR(1)  NOT NULL, -- Denotes the subtype discriminator.
    Foo              CHAR(30) NOT NULL,
    Bar              CHAR(30) NOT NULL,
    Baz              CHAR(30) NOT NULL,  
    CreatedDateTime  DATETIME NOT NULL,
    --
    CONSTRAINT Item_PK             PRIMARY KEY (ItemId),
    CONSTRAINT Item_to_Category_FK FOREIGN KEY (CategoryCode)
        REFERENCES Category    (CategoryCode),
    CONSTRAINT Item_to_User_FK     FOREIGN KEY (OwnerId)
        REFERENCES UserProfile (UserId)  
);

CREATE TABLE Car ( -- Represents one of the subtypes.
    CarId INT      NOT NULL, -- Must be constrained as (a) the PRIMARY KEY and (b) a FOREIGN KEY.
    Qux   CHAR(30) NOT NULL,
    Corge CHAR(30) NOT NULL,   
    --
    CONSTRAINT Car_PK         PRIMARY KEY (CarId),
    CONSTRAINT Car_to_Item_FK FOREIGN KEY (CarId)
        REFERENCES Item (ItemId)  
);

CREATE TABLE Boat ( -- Stands for one of the subtypes.
    BoatId INT      NOT NULL, -- Must be constrained as (a) the PRIMARY KEY and (b) a FOREIGN KEY.
    Grault CHAR(30) NOT NULL,
    Garply CHAR(30) NOT NULL,   
    Plugh  CHAR(30) NOT NULL, 
    --
    CONSTRAINT Boat_PK         PRIMARY KEY (BoatId),
    CONSTRAINT Boat_to_Item_FK FOREIGN KEY (BoatId)
        REFERENCES Item (ItemId)  
);

CREATE TABLE Plane ( -- Denotes one of the subtypes.
    PlaneId INT      NOT NULL, -- Must be constrained as (a) the PRIMARY KEY and (b) a FOREIGN KEY.
    Xyzzy   CHAR(30) NOT NULL,
    Thud    CHAR(30) NOT NULL,  
    Wibble  CHAR(30) NOT NULL,
    Flob    CHAR(30) NOT NULL,  
    --
    CONSTRAINT Plane_PK         PRIMARY KEY (PlaneId),
    CONSTRAINT Plane_to_Item_PK FOREIGN KEY (PlaneId)
        REFERENCES Item (ItemId)  
);

Wie gezeigt, ist der superentity Typ und jeder der Sub - Entität Typen durch die entsprechende dargestellte Basistabelle.

Die Spalten CarId, BoatIdund PlaneId, eingeschränkt , wie die PKs der entsprechenden Tabellen, Hilfe in der die konzeptionellen Ebene Eins-zu-Eins - Zuordnung haft FK Constraints § dieses Punkt zu der ItemIdSpalte, die als PK der gezwungen ist ItemTabelle. Dies bedeutet, dass in einem tatsächlichen „Paar“ sowohl die Supertyp- als auch die Subtypzeile durch denselben PK-Wert identifiziert werden. Daher ist es mehr als angebracht, dies zu erwähnen

  • (a) Das Anhängen einer zusätzlichen Spalte zum Halten systemgesteuerter Ersatzwerte an (b) die Tabellen, die für die Untertypen stehen, ist (c) völlig überflüssig .

§ Um Probleme und Fehler in Bezug auf (insbesondere AUSLÄNDISCHE) KEY-Einschränkungsdefinitionen zu vermeiden - Situation, auf die Sie in Kommentaren Bezug genommen haben -, ist es sehr wichtig, die Existenzabhängigkeit zu berücksichtigen, die zwischen den verschiedenen vorliegenden Tabellen auftritt , wie in dargestellt Die Deklarationsreihenfolge der Tabellen in der Expository-DDL-Struktur, die ich auch in dieser SQL-Geige angegeben habe.

Anhängen einer zusätzlichen Spalte mit der Eigenschaft AUTO_INCREMENT an eine Tabelle einer auf MySQL basierenden Datenbank.

Überlegungen zu Integrität und Konsistenz

Es ist wichtig darauf hinzuweisen, dass Sie in Ihrem Geschäftsumfeld (1) sicherstellen müssen, dass jede Zeile "Supertyp" jederzeit durch das entsprechende Gegenstück "Subtyp" ergänzt wird, und (2) dies wiederum garantieren Die Zeile "Subtyp" ist mit dem Wert kompatibel, der in der Spalte "Diskriminator" der Zeile "Supertyp" enthalten ist.

Es wäre sehr elegant, solche Umstände deklarativ durchzusetzen , aber leider hat meines Wissens keine der großen SQL-Plattformen die richtigen Mechanismen dafür bereitgestellt. Daher wird in ACID TRANSACTIONS auf Verfahrenscode zurückgegriffen ist es sehr praktisch, , damit diese Bedingungen in Ihrer Datenbank immer erfüllt sind. Eine andere Möglichkeit wäre der Einsatz von TRIGGERS, aber sie neigen dazu, die Dinge sozusagen unordentlich zu machen.

Nützliche Ansichten deklarieren

Ein logisches Design wie das mit dem oben erläuterte, wäre es sehr praktisch sein , eine oder mehr Ansichten zu erstellen, dh abgeleitete Tabellen , die Spalten enthalten, die zwei oder mehr der relevanten gehören Basistabellen. Auf diese Weise können Sie beispielsweise direkt AUS diesen Ansichten AUSWÄHLEN, ohne jedes Mal alle JOINs schreiben zu müssen, wenn Sie „kombinierte“ Informationen abrufen müssen.

Beispieldaten

Nehmen wir in diesem Zusammenhang an, dass die Basistabellen mit den unten gezeigten Beispieldaten „gefüllt“ sind:

--

INSERT INTO UserProfile 
    (UserId, FirstName, LastName, BirthDate, GenderCode, Username, CreatedDateTime)
VALUES
    (1, 'Edgar', 'Codd', '1923-08-19', 'M', 'ted.codd', CURDATE()),
    (2, 'Michelangelo', 'Buonarroti', '1475-03-06', 'M', 'michelangelo', CURDATE()),
    (3, 'Diego', 'Velázquez', '1599-06-06', 'M', 'd.velazquez', CURDATE());

INSERT INTO Category 
    (CategoryCode, Name)
VALUES
    ('C', 'Car'), ('B', 'Boat'), ('P', 'Plane');

-- 1. ‘Full’ Car INSERTion

-- 1.1 
INSERT INTO Item
    (ItemId, OwnerId, CategoryCode, Foo, Bar, Baz, CreatedDateTime)
VALUES
    (1, 1, 'C', 'This datum', 'That datum', 'Other datum', CURDATE());

 -- 1.2
INSERT INTO Car
    (CarId, Qux, Corge)
VALUES
    (1, 'Fantastic Car', 'Powerful engine pre-update!');

-- 2. ‘Full’ Boat INSERTion

-- 2.1
INSERT INTO Item
  (ItemId, OwnerId, CategoryCode, Foo, Bar, Baz, CreatedDateTime)
VALUES
  (2, 2, 'B', 'This datum', 'That datum', 'Other datum', CURDATE());

-- 2.2
INSERT INTO Boat
    (BoatId, Grault, Garply, Plugh)
VALUES
    (2, 'Excellent boat', 'Use it to sail', 'Everyday!');

-- 3 ‘Full’ Plane INSERTion

-- 3.1
INSERT INTO Item
  (ItemId, OwnerId, CategoryCode, Foo, Bar, Baz, CreatedDateTime)
VALUES
  (3, 3, 'P', 'This datum', 'That datum', 'Other datum', CURDATE());

-- 3.2
INSERT INTO Plane
    (PlaneId, Xyzzy, Thud, Wibble, Flob)
VALUES
    (3, 'Extraordinary plane', 'Traverses the sky', 'Free', 'Like a bird!');

--

Dann wird eine vorteilhafte Ansicht ist eine , die Raffungen Spalten aus Item, Carund UserProfile:

--

CREATE VIEW CarAndOwner AS
    SELECT C.CarId,
           I.Foo,
           I.Bar,
           I.Baz,
           C.Qux,
           C.Corge,           
           U.FirstName AS OwnerFirstName,
           U.LastName  AS OwnerLastName
        FROM Item I
        JOIN Car C
          ON C.CarId = I.ItemId
        JOIN UserProfile U
          ON U.UserId = I.OwnerId;

--

Natürlich kann ein ähnlicher Ansatz verfolgt werden, so dass Sie auch die "vollständigen" Boatund PlaneInformationen direkt aus einer einzigen Tabelle auswählen können (in diesen Fällen einer abgeleiteten) auswählen können.

Danach -wenn Sie nicht über das Vorhandensein von NULL Marken in Folge Sets- mit folgenden VIEW Definition etwas dagegen, können Sie, zB „collect“ Spalten aus den Tabellen Item, Car, Boat, Planeund UserProfile:

--

CREATE VIEW FullItemAndOwner AS
    SELECT I.ItemId,
           I.Foo, -- Common to all Categories.
           I.Bar, -- Common to all Categories.
           I.Baz, -- Common to all Categories.
          IC.Name      AS Category,
           C.Qux,    -- Applies to Cars only.
           C.Corge,  -- Applies to Cars only.
           --
           B.Grault, -- Applies to Boats only.
           B.Garply, -- Applies to Boats only.
           B.Plugh,  -- Applies to Boats only.
           --
           P.Xyzzy,  -- Applies to Planes only.
           P.Thud,   -- Applies to Planes only.
           P.Wibble, -- Applies to Planes only.
           P.Flob,   -- Applies to Planes only.
           U.FirstName AS OwnerFirstName,
           U.LastName  AS OwnerLastName
        FROM Item I
        JOIN Category IC
          ON I.CategoryCode = IC.CategoryCode
   LEFT JOIN Car C
          ON C.CarId = I.ItemId
   LEFT JOIN Boat B
          ON B.BoatId = I.ItemId
   LEFT JOIN Plane P
          ON P.PlaneId = I.ItemId               
        JOIN UserProfile U
          ON U.UserId = I.OwnerId;

--

Der Code der hier gezeigten Ansichten dient nur zur Veranschaulichung. Natürlich können einige Testübungen und Änderungen dazu beitragen, die (physische) Ausführung der vorliegenden Abfragen zu beschleunigen. Darüber hinaus müssen Sie möglicherweise Spalten entfernen oder zu diesen Ansichten hinzufügen, je nach den geschäftlichen Anforderungen.

Die Beispieldaten und alle Ansichtsdefinitionen sind in diese SQL-Geige integriert, damit sie „in Aktion“ beobachtet werden können.

Datenmanipulation: Code und Spaltenaliasnamen von Anwendungsprogrammen

Die Verwendung von Anwendungsprogrammcode (wenn Sie dies mit "serverseitigem spezifischem Code" meinen) und Spaltenaliasnamen sind weitere wichtige Punkte, die Sie in den nächsten Kommentaren angesprochen haben:

  • Ich habe es geschafft, [ein JOIN] -Problem mit serverseitigem Code zu umgehen, aber ich möchte wirklich nicht, dass das Hinzufügen von Aliasen zu allen Spalten "stressig" ist.

  • Sehr gut erklärt, vielen Dank. Wie ich jedoch vermutet habe, muss ich die Ergebnismenge beim Auflisten aller Daten aufgrund der Ähnlichkeiten mit einigen Spalten manipulieren, da ich nicht mehrere Aliase verwenden möchte, um die Anweisung sauberer zu halten.

Es ist angebracht anzugeben, dass die Verwendung von Anwendungsprogrammcode eine sehr geeignete Ressource für die Darstellung (oder grafische) Präsentationsfunktionen von Ergebnismengen ist. Die Vermeidung zeilenweiser Datenabrufe ist jedoch von größter Bedeutung, um Probleme mit der Ausführungsgeschwindigkeit zu vermeiden. Das Ziel sollte darin bestehen, die relevanten Datensätze mithilfe der robusten Datenmanipulationsinstrumente, die von der (genau) festgelegten Engine der SQL-Plattform bereitgestellt werden, vollständig abzurufen, damit Sie das Verhalten Ihres Systems optimieren können.

Darüber hinaus mag die Verwendung von Aliasen zum Umbenennen einer oder mehrerer Spalten innerhalb eines bestimmten Bereichs stressig erscheinen, aber ich persönlich sehe diese Ressource als ein sehr leistungsfähiges Werkzeug, das hilft, (i) die Bedeutung und Absicht zu kontextualisieren und (ii) zu disambiguieren zugeschriebene zu Säulen; Daher ist dies ein Aspekt, über den im Hinblick auf die Manipulation der interessierenden Daten gründlich nachgedacht werden sollte.

Ähnliche Szenarien

Sie können genauso gut Hilfe bei dieser Reihe von Beiträgen und dieser Gruppe von Beiträgen finden , die meine Meinung zu zwei anderen Fällen enthalten, die Supertyp-Subtyp-Assoziationen mit sich gegenseitig ausschließenden Subtypen enthalten.

Ich habe auch eine Lösung für eine Geschäftsumgebung vorgeschlagen, die einen Supertyp-Subtyp-Cluster umfasst, bei dem sich die Subtypen in dieser (neueren) Antwort nicht gegenseitig ausschließen .


Endnoten

1 Integration Definition für Information Modeling ( IDEF1X ) ist eine sehr empfehlenswerte Datenmodellierungstechnik, die als etabliert wurde Standard im Dezember 1993 von der US National Institute of Standards and Technology (NIST). Es basiert fest auf (a) einigen theoretischen Arbeiten, die vom alleinigen Urheber des relationalen Modells verfasst wurden , dh Dr. EF Codd ; zu (b) dervon Dr. PP Chen entwickelten Entity-Relationship-Sicht ; und auch auf (c) der Logical Database Design Technique, erstellt von Robert G. Brown.

2 In IDEF1X ein Rollenname ist eine unterscheidende Markierung an einer FKEigenschaft zugewiesen (oder Attribut), um die Bedeutung auszudrückendass es im Rahmen seiner jeweiligen Entitätstyp hält.

3 Der IDEF1X-Standard definiert die Schlüsselmigration als „Modellierungsprozess zum Platzieren des Primärschlüssels einer übergeordneten oder generischen Entität in ihrer untergeordneten oder Kategorie-Entität als Fremdschlüssel“.


1
Ich bin nicht sicher, ob ich Ihre Anfrage verstehe, aber wie im DDL-Layout dargestellt, enthält die ItemTabelle eine CategoryCodeSpalte. Wie im Abschnitt "Überlegungen zu Integrität und Konsistenz" erwähnt:
MDCCL

1
Es ist wichtig darauf hinzuweisen, dass Sie in Ihrem Geschäftsumfeld (1) sicherstellen müssen, dass jede Zeile "Supertyp" jederzeit durch das entsprechende Gegenstück "Subtyp" ergänzt wird, und (2) dies wiederum garantieren Die Zeile "Subtyp" ist mit dem Wert kompatibel, der in der Spalte "Diskriminator" der Zeile "Supertyp" enthalten ist.
MDCCL

1
Es wäre sehr elegant, solche Umstände deklarativ durchzusetzen, aber leider hat meines Wissens keine der großen SQL-Plattformen die richtigen Mechanismen dafür bereitgestellt. Daher ist es sehr praktisch, in ACID TRANSACTIONS auf Verfahrenscode zurückzugreifen, damit diese Bedingungen in Ihrer Datenbank immer erfüllt sind. Eine andere Möglichkeit wäre der Einsatz von TRIGGERS, aber sie neigen dazu, die Dinge sozusagen unordentlich zu machen.
MDCCL

1
Der Kern der Sache ist, dass keine SQL-Implementierung (einschließlich des MySQL-Dialekts) ASSERTIONS, leistungsstarke und elegante deklarative Tools, die dazu beitragen würden, nicht auf prozedurale Ansätze (TRANSACTIONS oder TRIGGERS) zurückzugreifen oder redundant zu arbeiten, ordnungsgemäß unterstützt B. unnötiges Wiederholen CategoryColumnder Tabellen, die für die Untertypen stehen (mit allen Auswirkungen auf die logischen [z. B. Modifikationsanomalien] und physischen Abstraktionsebenen [z. B. zusätzliche Indizes, größere Strukturen usw.]).
MDCCL

2
Bis einer der Anbieter / Entwickler von Datenbankverwaltungssystemen ASSERTIONS - das richtige Werkzeug für diese Aufgabe - bereitstellt, bevorzuge ich (a) die prozeduralen Ansätze - seien es TRANSAKTIONEN oder TRIGGER - gegenüber (b) der redundanten Vorgehensweise, obwohl (b) ist eine Möglichkeit - die ich persönlich nicht empfehle -. Natürlich muss der DBA die Berechtigungen für die gültigen Datenmanipulationsvorgänge, die in der relevanten Datenbank ausgeführt werden können, sorgfältig verwalten, was bei der Aufrechterhaltung der Datenintegrität sehr hilfreich ist.
MDCCL

0

Nennen wir die Haupttabelle Produkte. Hier werden die gemeinsam genutzten Attribute gehostet. Dann nehmen wir an, wir haben einen Autotisch, einen Flugzeugtisch und einen Bootstisch. Diese drei Tabellen hätten einen ProductID-Schlüssel mit einer FK-Einschränkung in der ID-Zeile der Product-Tabelle. Wenn Sie sie alle wollen - schließen Sie sich ihnen an. Wenn Sie nur die Autos wollen, verbinden Sie links Autos mit Produkten (oder rechts verbinden Sie Produkte und Autos, aber ich bevorzuge immer linksseitige Verbindungen).

Dies wird als hiearchisches Datenmodell bezeichnet. Bei einer geringen Anzahl von Untertabellen kann dies in einer langen Tabelle (Millionen von Produkten) sinnvoll sein.


Und dann schließe ich mich Benutzern mit Produkten an?
user5613506

1
Normalerweise benötigen Sie keine Benutzerinformationen, wenn Sie eine Produktliste an Ihr Front-End zurücksenden. Sie benötigen die Produktinformationen. Es ist nicht sinnvoll, Benutzer und Produkte zu verbinden und die identischen Benutzerinformationen für jede zurückgegebene Produktzeile zurückzugeben. Sie filtern also zuerst nach Produkttyp, indem Sie die Produkttabelle und die entsprechende Untertabelle (Auto, Boot ...) zusammenfügen, und filtern dann nach Benutzer mithilfe einer WHERE-Klausel. Im Allgemeinen möchten Sie eine OwnerID in der Produkttabelle haben (eine FK in der ID-Spalte der Benutzertabelle). Sie würden also einen WHERE-Besitzer = [Request.User] hinzufügen.
neManiac
Durch die Nutzung unserer Website bestätigen Sie, dass Sie unsere Cookie-Richtlinie und Datenschutzrichtlinie gelesen und verstanden haben.
Licensed under cc by-sa 3.0 with attribution required.