Inspirowane pytaniem dotyczącym modelowania Django: Modelowanie bazy danych z wieloma relacjami wiele do wielu w Django . DB-design jest podobny do:
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)
) ;
problem polega na tym, jak zdefiniować BookAspectRating
tabelę i wymusić integralność referencyjną, więc nie można dodać oceny dla (Book, Aspect)
kombinacji, która jest nieprawidłowa.
AFAIK, złożone CHECK
ograniczenia (lub ASSERTIONS
), które obejmują podzapytania i więcej niż jedną tabelę, które mogłyby rozwiązać ten problem, nie są dostępne w żadnym DBMS.
Innym pomysłem jest użycie (pseudokodu) widoku:
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) ;
oraz tabelę, która ma klucz obcy do powyższego widoku:
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)
) ;
Trzy pytania:
Czy istnieją DBMS, które pozwalają (ewentualnie zmaterializować) się
VIEW
zPRIMARY KEY
?Czy istnieją DBMS, które pozwalają
FOREIGN KEY
, żeREFERENCES
jestVIEW
(a nie tylko podstawyTABLE
)?Czy problem integralności mógłby zostać rozwiązany w inny sposób - dzięki dostępnym funkcjom DBMS?
Wyjaśnienie:
Ponieważ prawdopodobnie nie ma w 100% satysfakcjonującego rozwiązania - a pytanie Django nie jest nawet moje! - Bardziej interesuje mnie ogólna strategia możliwego ataku na problem, a nie szczegółowe rozwiązanie. Tak więc odpowiedź typu „w DBMS-X można to zrobić za pomocą wyzwalaczy z tabeli A” jest całkowicie akceptowalna.