Натхненний питанням моделювання Джанго: Моделювання баз даних з безліччю відносин багато-багато-багато в Джанго . Дизайн db - це щось на зразок:
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)
) ;
і питання полягає в тому, як визначити BookAspectRating
таблицю та застосувати референтну цілісність, тому не можна додавати рейтинг для (Book, Aspect)
недійсної комбінації.
AFAIK, складні CHECK
обмеження (або ASSERTIONS
), які містять підзапити та більше однієї таблиці, які могли б вирішити це, не доступні в жодній СУБД.
Інша ідея - використовувати (псевдокод) вид:
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) ;
та таблиця із зовнішнім ключем до наведеного вище перегляду:
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)
) ;
Три питання:
Чи є СУБД, які дозволяють (можливо, матеріалізуватися)
VIEW
зPRIMARY KEY
?Чи існують СУБД , які дозволяють ,
FOREIGN KEY
щоREFERENCES
вVIEW
(а не тільки базиTABLE
)?Чи можна вирішити цю проблему цілісності інакше - з наявними функціями СУБД?
Пояснення:
Оскільки, мабуть, немає 100% задовольняючого рішення - і питання Джанго навіть не моє! - Мене більше цікавить загальна стратегія можливого нападу на проблему, а не детальне рішення. Отже, відповідь на кшталт "у СУБД-X це можна зробити за допомогою тригерів на таблиці А" цілком прийнятна.