patternModerate
Are there DBMS that allow a Foreign Key that References a View (and not only base tables)?
Viewed 0 times
tablesareforeignviewallowbasethatdbmsandthere
Problem
Inspired by a Django modeling question: Database Modeling with multiple many-to-many relations in Django. The db-design is something like:
and the issue is how to define the
AFAIK, complex
Another idea is to use (pseudocode) a view:
and a table that has a Foreign Key to the above View:
Three questions:
-
Are there DBMS that allow a (possibly materialized)
-
Are there DBMS that allow a
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)
) ;and the issue is how to define the
BookAspectRating table and to enforce referential integrity, so one cannot add a rating for a (Book, Aspect) combination that is invalid.AFAIK, complex
CHECK constraints (or ASSERTIONS) that involve subqueries and more than one table, that could possibly solve this, are not available in any DBMS.Another idea is to use (pseudocode) a view:
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) ;and a table that has a Foreign Key to the above View:
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)
) ;Three questions:
-
Are there DBMS that allow a (possibly materialized)
VIEW with a PRIMARY KEY?-
Are there DBMS that allow a
Solution
In Oracle, one way to enforce this sort of constraint in a declarative fashion would be to create a materialized view that is set to refresh fast on commit whose query identifies all the invalid rows (i.e.
BookAspectRating rows that have no match in BookAspect_view). You can then create a trivial constraint on that materialized view that would be violated if there are any rows in the materialized view. This has the benefit of minimizing the amount of data that you have to duplicate in the materialized view. It can cause problems, however, since the constraint is only enforced at the point that you're committing the transaction-- many applications aren't written to expect that a commit operation might fail-- and because the constraint violation can be somewhat hard to associate with a particular row or a particular table.Context
StackExchange Database Administrators Q#17853, answer score: 10
Revisions (0)
No revisions yet.