Database-Design

強制執行“至少一個”關係

  • July 15, 2021

多對多(數據模型)維基百科文章使用了作者和書籍的例子:

例如,將 A 視為作者,將 B 視為書籍。一個作者可以寫幾本書,而一本書可以由幾個作者寫。

在關係數據庫管理系統中,這種關係通常通過關聯表(也稱為交叉引用表)來實現,例如,AB 具有兩個一對多關係 A -> AB 和 B -> AB。在這種情況下,AB 的邏輯主鍵由兩個外鍵(即 A 和 B 的主鍵的副本)形成。

有了約束,你將如何強制一本書必須****至少有一個作者?

筆記:

  • 對於此範例,沒有“主要”作者之類的東西。
  • 用 SQL(任何 RDBMS)或一般術語回答。

如何在 SQL 中執行此操作,僅使用 DDL(FOREIGN KEYUNIQUE約束):

CREATE TABLE author
( author_id INT NOT NULL,
 author_name VARCHAR(100),
 CONSTRAINT author_pk
   PRIMARY KEY (author_id)
) ;

CREATE TABLE book
( book_id INT NOT NULL,
 book_title VARCHAR(100),
 CONSTRAINT book_pk
 PRIMARY KEY (book_id)
) ;

CREATE TABLE book_author  
( book_id INT NOT NULL,
 author_id INT NOT NULL,
 CONSTRAINT book_author_pk
   PRIMARY KEY (book_id, author_id),
 CONSTRAINT book__book_author_fk
   FOREIGN KEY (book_id) REFERENCES book (book_id),
 CONSTRAINT author__book_author_fk
   FOREIGN KEY (author_id) REFERENCES author (author_id)
) ;

到目前為止,這僅在書籍和作者之間實現了常見的多對多關係。這意味著一本書可以有 0、1 或多個作者,而一個作者可以有 0、1 或多本書。

如果我們想要嚴格的*“一本書必須****至少有 1 個作者”*,我們可以在其中添加另一列book和附加約束:

ALTER TABLE book
 ADD COLUMN author_id INT NOT NULL,
 ADD CONSTRAINT book_must_have_at_least_1_author_fk
   FOREIGN KEY (book_id, author_id) 
   REFERENCES book_author (book_id, author_id) ;

筆記:

  • 為了使上述約束起作用,我們需要一個已經實現可延遲約束(例如 Postgres、Oracle)或可以在一個語句中插入/刪除多個表(Postgres)的 DBMS。如果沒有這些,我們可以放寬一些限制,例如通過 3 個步驟來解除NOT NULLbook (author_id)插入(比如一本新書):

    • 插入書中(author_id 為空)
    • 插入 book_author
    • 更新書籍(相應地設置 author_id)。然後我們可以將上述步驟包裝在事務/過程中,然後僅通過這些事務/過程限制對錶的訪問(每個操作一個過程,插入新書及其作者,刪除書籍及其作者,更新作者,刪除作者從書等)。

如果不是很明顯,這些程序可能會變得有點複雜,例如當必須刪除一本書的“主要”作者時,因為該程序必須搜尋其餘作者並book.author_id相應更新或失敗/拒絕刪除,如果沒有其他作者離開了。

  • 另一種選擇——因為我們提到了程序——是從一開始就將它們用於所有插入/更新/刪除操作。如果設計和測試正確,它們可以強制執行所有約束,允許不聲明任何外鍵。

引用自:https://dba.stackexchange.com/questions/167923