Inspirado por uma pergunta de modelagem do Django: Modelagem de Banco de Dados com várias relações muitos-para-muitos no Django . O design do db é algo como:
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)
) ;

e o problema é como definir a BookAspectRatingtabela e impor a integridade referencial; portanto, não é possível adicionar uma classificação para uma (Book, Aspect)combinação inválida.
AFAIK, CHECKrestrições complexas (ou ASSERTIONS) que envolvem subconsultas e mais de uma tabela, que poderia resolver isso, não estão disponíveis em nenhum DBMS.
Outra idéia é usar (pseudocódigo) uma visão:
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) ;
e uma tabela que possui uma chave estrangeira para a exibição acima:
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)
) ;
Três perguntas:
Existem DBMS que permitem um (possivelmente materializado)
VIEWcom umPRIMARY KEY?Existem DBMS que permitem que um
FOREIGN KEYqueREFERENCESumVIEW(e não apenas uma baseTABLE)?Esse problema de integridade poderia ser resolvido de outra forma - com os recursos DBMS disponíveis?
Esclarecimento:
Como provavelmente não existe uma solução 100% satisfatória - e a questão do Django nem sequer é minha! - Estou mais interessado em uma estratégia geral de possível ataque ao problema, não em uma solução detalhada. Portanto, uma resposta como "no DBMS-X isso pode ser feito com gatilhos na tabela A" é perfeitamente aceitável.