Postgresql
這個多對多表可以改進嗎?
我正在創建一個數據庫,使用者可以在其中添加許多書籍。一本書可以被許多使用者閱讀。我正在使用 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 );
由於我對數據庫不是很熟悉,所以我有以下問題:
users_books
表中,使用是否免於PRIMARY KEY (user_id, book_id)
使用user_id
列,還是仍然是強制性的?- 有沒有辦法根據另一個表接收到的資訊自動填充一個表?例如,如果我提供 users 和 books 表, users_books 表可以提供自己嗎?
- 是否建議我使用 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。
根據您的描述,我猜想涉及兩個動詞:
- Add_book
- 讀書
第一個通常是 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 列太複雜)。
添加一個可以用作主鍵的代理屬性可能是有意義的,但根據經驗,不要這樣做,做出有意識的決定。
如果您認為最好的選擇是使用代理鍵,請確保為自然鍵添加唯一約束(有時稱為備用鍵)。