Ispirato da una domanda di modellazione di Django: Modellazione di database con molteplici relazioni molti-a-molti in Django . Il db-design è qualcosa di simile:
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 il problema è come definire la BookAspectRating
tabella e imporre l'integrità referenziale, quindi non è possibile aggiungere una valutazione per una (Book, Aspect)
combinazione non valida.
AFAIK, CHECK
vincoli complessi (o ASSERTIONS
) che coinvolgono sottoquery e più di una tabella, che potrebbero eventualmente risolverlo, non sono disponibili in nessun DBMS.
Un'altra idea è quella di utilizzare (pseudocodice) una vista:
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 una tabella che ha una chiave esterna per la vista sopra:
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)
) ;
Tre domande:
Esistono DBMS che consentono un (possibilmente materializzato)
VIEW
con unPRIMARY KEY
?Esistono DBMS che consentono a
FOREIGN KEY
cheREFERENCES
aVIEW
(e non solo una baseTABLE
)?Questo problema di integrità potrebbe essere risolto altrimenti - con le funzionalità DBMS disponibili?
Una precisazione:
Dal momento che probabilmente non esiste una soluzione soddisfacente al 100% - e la domanda di Django non è nemmeno mia! - Sono più interessato a una strategia generale di possibile attacco al problema, non a una soluzione dettagliata. Quindi, una risposta come "in DBMS-X questo può essere fatto con i trigger nella tabella A" è perfettamente accettabile.