Postgresql

這個多對多表可以改進嗎?

  • July 7, 2021

我正在創建一個數據庫,使用者可以在其中添加許多書籍。一本書可以被許多使用者閱讀。我正在使用 PostgreSQL 並設置以下結構:

CREATE TABLE users(
   uid SERIAL PRIMARY KEY,
   email VARCHAR(25) UNIQUE NOT NULL,
   hash TEXT NOT NULL,
   first_name VARCHAR(30),
   last_name VARCHAR(80)
);

CREATE TABLE books(
   bid VARCHAR(30) PRIMARY KEY,
   title VARCHAR(40) NOT NULL,
   author VARCHAR(40) NOT NULL,
   thumbnail TEXT
);

CREATE TABLE users_books(
   user_id INTEGER NOT NULL,
   book_id VARCHAR(30) NOT NULL,
   date_added DATE NOT NULL DEFAULT CURRENT_DATE,
   PRIMARY KEY (user_id, book_id),
   FOREIGN KEY (user_id) REFERENCES users(uid) ON UPDATE CASCADE,
   FOREIGN KEY (book_id) REFERENCES books(bid) ON UPDATE CASCADE
);

由於我對數據庫不是很熟悉,所以我有以下問題:

  1. users_books表中,使用是否免於PRIMARY KEY (user_id, book_id)使用user_id列,還是仍然是強制性的?
  2. 有沒有辦法根據另一個表接收到的資訊自動填充一個表?例如,如果我提供 users 和 books 表, users_books 表可以提供自己嗎?
  3. 是否建議我使用 3 個表來實現此人添加書籍的目標?或者最值得推薦的是使用 2 張桌子?

最後,我想知道你會做什麼不同的事情。

我不確定我是否理解你的第一個問題,但我會試一試。業務規則:

使用者可以添加 0 或 1 本書將意味著如下約束:

ALTER TABLE users_books PRIMARY KEY (user_id)

另一方面,像這樣的規則:

每本書可以由 0 或 1 個使用者添加,這意味著如下約束:

ALTER TABLE users_books PRIMARY KEY (book_id)

如果規則是使用者可以添加圖書 0 次或 1 次,即使該圖書已被其他使用者添加,規則將是:

ALTER TABLE users_books PRIMARY KEY (user_id, book_id)

如果使用者可以每天添加一次同一本書,請在約束中包含 date_added。

所以答案是,這取決於你想要實現什麼 BR。

根據您的描述,我猜想涉及兩個動詞:

  1. Add_book
  2. 讀書

第一個通常是 books 表的一個屬性:

CREATE TABLE books(
   bid VARCHAR(30) PRIMARY KEY,
   title VARCHAR(40) NOT NULL,
   author VARCHAR(40) NOT NULL,
   thumbnail TEXT,
   added_by_user ... references users (uid)
);

第二個通常會按照您的方式實施

2 的答案可能不是。該關係表示哪些使用者添加了哪些書籍。如果沒有 user_books 表的內容,通常無法弄清楚這一點。如果 user_books 只是使用者和書籍之間的笛卡爾積,您可以將其替換為視圖:

CREATE VIEW users_books as
SELECT u.uid AS user_id, b.bid AS bookid
FROM users u
CROSS JOIN books b

我想我已經回答了 3)所以我會添加一些想法

  • 如果可能,請使用完善的標準。在您的情況下,您可以考慮使用 ISBN 來辨識一本書
  • 在整個模型中使用相同的標識符。如果您使用 uid 作為使用者的標識符,請在模​​型的其他表中使用該標識符
  • 嘗試為您的關係找到有意義的名稱。如果 user_books 表示哪些使用者已經閱讀了哪些書籍。試著想出一個能反映這一點的名字。

關於如何設計好的主鍵/唯一約束我的兩分錢

它應該是:

  • 獨一無二——當然
  • 熟悉 - 它應該是您的業務中存在的東西
  • 不可約——列的任何子集都不應該是唯一的
  • 穩定——不應該經常變化
  • 不復雜——它不應該包含太多的列

通常一個人不能滿足所有這些,一個人不得不選擇一個而不是另一個。熟悉與不復雜通常處於危險之中(我通常不認為 2 列太複雜)。

添加一個可以用作主鍵的代理屬性可能是有意義的,但根據經驗,不要這樣做,做出有意識的決定。

如果您認為最好的選擇是使用代理鍵,請確保為自然鍵添加唯一約束(有時稱為備用鍵)。

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