受到Django建模问题的启发:Django中具有多个多对多关系的数据库建模。数据库设计类似于:
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
)涉及子查询和一个以上的表(可能解决此问题),在任何DBMS中均不可用。
另一个想法是使用(伪代码)视图:
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)
) ;
三个问题:
是否有DBMS允许(可能实现)
VIEW
带有PRIMARY KEY
?是否有DBMS允许一个
FOREIGN KEY
是REFERENCES
一个VIEW
(而不仅仅是基础TABLE
)?是否可以使用可用的DBMS功能来解决此完整性问题?
澄清:
由于可能没有100%令人满意的解决方案-Django问题甚至不是我的!-我对可能对问题进行攻击的一般策略而不是详细的解决方案更感兴趣。因此,完全可以接受诸如“在DBMS-X中可以通过表A上的触发器来完成”这样的答案。