我有兩個表格和有聲讀物,它們都以ISBN爲主鍵。我有一個表格,它有一個isbn屬性,它有一個外鍵約束書籍和有聲讀物ISBN。當我插入到書面時出現的問題是,postgresql想要我插入到書寫的ISBN中以便出現在書籍和有聲讀物中。對於我來說,有一個由商店作者和他們編寫的書籍/有聲讀物編寫的表格是有意義的,但是這並不會轉化爲postgresql中的表格。我正在考慮的另一種解決方案是有兩個新的關係audiobook_writtenby和books_writtenby,但我不確定這是一個好的選擇。你能否告訴我如何實現我最初的想法:通過引用兩個不同的表來寫一張表,或者如何更好地設計我的數據庫。如果您需要更多信息,請與我們聯繫。POSTGRESQL外鍵引用兩個不同表格的主鍵
回答
RDBMS不支持多態外鍵約束。你想要做的事情是合理的,但是在關係模型中並沒有很好地適應這種情況,並且在製作ORM系統時不能很好地解決對象關係阻抗不匹配的實際問題之一。 Nice discussion on this on Ward's WIki
解決問題的一種方法可能是製作單獨的表known_isbns,並在Books和AudioBook上設置約束和/或觸發器,以便表包含這兩種類型特定書籍表的所有有效isbns。然後你寫的FK約束將檢查known_isbns。
你可以使用表繼承,以獲得兩全其美。使用引用書寫表的INHERITS
子句創建audiobook_writtenby和books_writtenby。外鍵可以按照您的描述在子級別定義,但您仍然可以在較高級別引用數據。 (你也可以用視圖做到這一點,但它聽起來像是繼承可能是在這種情況下,更清潔。)
請參閱該文檔:
http://www.postgresql.org/docs/current/interactive/sql-createtable.html
http://www.postgresql.org/docs/current/interactive/tutorial-inheritance.html
http://www.postgresql.org/docs/current/interactive/ddl-inherit.html
請注意,如果您這樣做,您可能需要在書寫的表格上添加BEFORE INSERT觸發器。
在PostgreSQL中有多種方法可以做到這一點。就我個人而言,我更喜歡這種方式。
-- This table should contain all the columns common to both
-- audio books and printed books.
create table books (
isbn char(13) primary key,
title varchar(100) not null,
book_type char(1) not null default 'p'
check(book_type in ('a', 'p')),
-- This unique constraint lets the tables books_printed and books_audio
-- target the isbn *and* the type in a foreign key constraint.
-- This prevents you from having an audio book in this table
-- linked to a printed book in another table.
unique (isbn, book_type)
);
-- Columns unique to printed books.
create table books_printed (
isbn char(13) primary key references books (isbn),
-- Allows only one value. This plus the FK constraint below guarantee
-- that this row will relate to a printed book row, not an audio book
-- row, in the table books. The table "books_audio" is similar.
book_type char(1) default 'p'
check (book_type = 'p'),
foreign key (isbn, book_type) references books (isbn, book_type),
other_columns_for_printed_books char(1) default '?'
);
-- Columns unique to audio books.
create table books_audio (
isbn char(13) primary key references books (isbn),
book_type char(1) default 'a'
check (book_type = 'a'),
foreign key (isbn, book_type) references books (isbn, book_type),
other_columns_for_audio_books char(1) default '?'
);
-- Authors are common to both audio and printed books, so the isbn here
-- references the table of books.
create table book_authors (
isbn char(13) not null references books (isbn),
author_id integer not null references authors (author_id), -- not shown
primary key (isbn, author_id)
);
在這個特定的例子中,絕對不需要使用多個表。只要使用表格「Book」並添加「AudioBook」的列(如果適用)即可。如果您必須在具有特定列的表級別上進行區分,請創建視圖。您是否檢查過具有相同內容的「書」和「音頻書」是否具有相同的ISBN?
即使你的答案在技術上是正確的,但我不認爲應該遵循它。 PostgreSQL支持非常好的建模。把多個物體摺疊成一張桌子通常會變成一團糟。 – Theuni 2016-09-23 19:19:43
- 1. 一個外鍵引用不同表的兩個主鍵?
- 2. SQL,兩個外鍵引用另一個表的相同主鍵
- 3. Mysql外鍵引用兩個列,它們是兩個不同表中的主鍵
- 4. 對外鍵的兩個主鍵引用
- 5. 不同表格的兩個主鍵作爲另一個表的外鍵
- 6. 數據建模兩個引用相同主鍵的外鍵
- 7. 主鍵是兩個不同的互斥表的外鍵
- 8. 向同一主表的兩個外鍵
- 9. 來自兩個不同表的兩個不同主鍵的外鍵引用是否有效?
- 10. PostgreSQL的引用外鍵的多個表
- 11. 創建具有複合主鍵的表引用兩個外鍵
- 12. PostgreSQL - 引用多個表的外鍵
- 13. 從兩個外鍵引用到兩個不同的表使複合鍵錯誤
- 14. 連接兩個表的主鍵和外鍵具有不同格式
- 15. 複合主鍵與兩個不同的表中的兩個外鍵mvc
- 16. 如何使用不同的主鍵/外鍵加入表格
- 17. 同一個表和外鍵上的兩個主鍵
- 18. postgreSQL主/外鍵不符合
- 19. 引用相同列的兩個外鍵
- 20. 每個表有四個外鍵不能引用主表中的單個主鍵
- 21. 多個外鍵同主鍵表
- 22. SQL外鍵,兩個不同的表
- 23. QSqlRelationalTableModel - 兩個引用同一個表,相同的外鍵
- 24. 對同一表中的主鍵的外鍵引用EF6
- 25. 有兩個外鍵約束引用同一個主鍵,都使用ON UPDATE CASCADE
- 26. 兩個外鍵引用一個表
- 27. 兩個外鍵引用另一個表
- 28. 跨2個表引用2個主鍵的外鍵?
- 29. 引用同一主鍵的一個表的多個列的外鍵?
- 30. 一個外鍵和兩個主鍵
關係模型和SQL數據庫實際上處理這種事情。問題不是關係型或SQL;問題在於其中一個顯而易見的限制是錯誤地實現的。 (約束條件是書籍和有聲讀物的ISBN是從相同的域中抽取的。) – 2012-04-09 18:17:17