문제

I have three tables: a users table, a books table, and a chapters table.

Each book has an id called identifier_id (for good business reasons that I cannot work around). This id is guaranteed to be unique per-user, i.e. no user will ever have two books with the same id. It is not, however, guaranteed to be globally unique. Each book also has a foreign key user_id.

Each chapter has user_id and book_id foreign keys - the book_id foreign key points to identifier_id on the books table.

When I add chapters to a book, I want to add a database-level contraint that a chapter insert will be rejected unless the user_id of the chapter matches the user_id of the book AND the book_id of the chapter matches a book_id in the books table.

Because the book_id is not globally unique, I cannot put a unique index on it. Is there a way to do this?

도움이 되었습니까?

해결책

You can create a unique compound index

 CREATE UNIQUE INDEX "book_id_user" ON books (identifier_id,user_id);

And then you can create a F.K. constraint

 ALTER TABLE chapters 
   ADD CONSTRAINT "FK_chapter_book" 
     FOREIGN KEY (book_id,user_id)
       REFERENCES books (identifier_id,user_id);

If you have any bad data that will need to be corrected before the constraint can be created

다른 팁

You need both the book ID and the user ID to identify a book, so both columns together are the primary key:

CREATE TABLE books (
    book_id  integer,
    user_id  integer REFERENCES users(user_id),
    ...,
    PRIMARY KEY (identifier_id, user_id)
);

So when you then declare that a chapter must reference a book, the constraint must use both IDs, and everything comes out right:

CREATE TABLE chapters (
    ...,
    book_id  integer,
    user_id  integer,
    FOREIGN KEY (book_id, user_id) REFERENCES books (book_id, user_id)
);
라이센스 : CC-BY-SA ~와 함께 속성
제휴하지 않습니다 dba.stackexchange
scroll top