Inspiriert von einer Django-Modellierungsfrage: Datenbankmodellierung mit mehreren Viele-zu-Viele-Beziehungen in Django . Das DB-Design ist so etwas wie:
CREATE TABLE Book
( BookID INT NOT NULL
, BookTitle VARCHAR(200) NOT NULL
, PRIMARY KEY (BookID)
) ;
CREATE TABLE Tag
( TagID INT NOT NULL
, TagName VARCHAR(50) NOT NULL
, PRIMARY KEY (TagID)
) ;
CREATE TABLE BookTag
( BookID INT NOT NULL
, TagID INT NOT NULL
, PRIMARY KEY (BookID, TagID)
, FOREIGN KEY (BookID) REFERENCES Book (BookID)
, FOREIGN KEY (TagID) REFERENCES Tag (TagID)
) ;
CREATE TABLE Aspect
( AspectID INT NOT NULL
, AspectName VARCHAR(50) NOT NULL
, PRIMARY KEY (AspectID)
) ;
CREATE TABLE TagAspect
( TagID INT NOT NULL
, AspectID INT NOT NULL
, PRIMARY KEY (TagID, AspectID)
, FOREIGN KEY (TagID) REFERENCES Tag (TagID)
, FOREIGN KEY (AspectID) REFERENCES Aspect (AspectID)
) ;
und das Problem ist, wie die BookAspectRating
Tabelle definiert und die referenzielle Integrität erzwungen wird, sodass für eine (Book, Aspect)
ungültige Kombination keine Bewertung hinzugefügt werden kann .
AFAIK, komplexe CHECK
Einschränkungen (oder ASSERTIONS
), die Unterabfragen und mehr als eine Tabelle umfassen, die dies möglicherweise lösen könnten, sind in keinem DBMS verfügbar.
Eine andere Idee ist, eine Ansicht zu verwenden (Pseudocode):
CREATE VIEW BookAspect_view
AS
SELECT DISTINCT
bt.BookId
, ta.AspectId
FROM
BookTag AS bt
JOIN
Tag AS t ON t.TagID = bt.TagID
JOIN
TagAspect AS ta ON ta.TagID = bt.TagID
WITH PRIMARY KEY (BookId, AspectId) ;
und eine Tabelle mit einem Fremdschlüssel für die obige Ansicht:
CREATE TABLE BookAspectRating
( BookID INT NOT NULL
, AspectID INT NOT NULL
, PersonID INT NOT NULL
, Rating INT NOT NULL
, PRIMARY KEY (BookID, AspectID, PersonID)
, FOREIGN KEY (PersonID) REFERENCES Person (PersonID)
, FOREIGN KEY (BookID, AspectID)
REFERENCES BookAspect_view (BookID, AspectID)
) ;
Drei Fragen:
Gibt es DBMS, die ein (eventuell materialisiertes)
VIEW
mit a erlaubenPRIMARY KEY
?Gibt es DBMS, die ein,
FOREIGN KEY
dassREFERENCES
einVIEW
(und nicht nur eine BasisTABLE
) ermöglichen?Könnte dieses Integritätsproblem anders gelöst werden - mit verfügbaren DBMS-Funktionen?
Klärung:
Da gibt es wohl keine 100% befriedigende Lösung - und die Django-Frage ist nicht mal meine! - Ich bin mehr an einer allgemeinen Strategie für einen möglichen Angriff auf das Problem interessiert, nicht an einer detaillierten Lösung. Eine Antwort wie "in DBMS-X kann dies mit Triggern in Tabelle A erfolgen" ist daher durchaus akzeptabel.