[英]multiple foreign keys as primary key postgres, should I do it?
This is one of those: why I should or why I should not.这是其中之一:为什么我应该或为什么我不应该。
So my books app has reviews, but one user must not review the same book more than one time.所以我的图书应用程序有评论,但一个用户不得多次评论同一本书。 In my point of view makes sense to create a table for the reviews and make the user_id and the book_id (ISBN) as the PRIMARY KEY for the reviews table.
在我看来,为评论创建一个表并将 user_id 和 book_id (ISBN) 作为评论表的主键是有意义的。 But, could it be a problem at some point if the application gets too many reviews, for example, could that decision slow the queries?
但是,如果应用程序获得太多评论,是否会在某个时候成为问题,例如,该决定会减慢查询速度吗?
I am using postgres and I am not sure if the following code is correct:我正在使用 postgres,但不确定以下代码是否正确:
CREATE TABLE users(
user_id PRIMARY KEY SERIAL,
user_name VARCHAR NOT NULL UNIQUE,
pass_hash VARCHAR NOT NULL,
email VARCHAR NOT NULL UNIQUE,
);
CREATE TABLE books(
book_id PRIMARY KEY BIGINT,
author VARCHAR NOT NULL,
title VARCHAR NOT NULL,
year INT NOT NULL CHECK (year > 1484),
review_count INT DEFAULT 0 NOT NULL,
avrg_score FLOAT,
);
CREATE TABLE reviews(
user_id INT FOREIGN KEY REFERENCES users(user_id) NOT NULL
book_id INT FOREIGN KEY REFERENCES books(book_id) NOT NULL
score INT NOT NULL CHECK (score > 0, score < 11)
PRIMARY KEY (book_id, user_id)
);
This is a perfectly valid design choice.这是一个完全有效的设计选择。
You have a many-to-many relationship between books and users, which is represented by the reviews
table.书籍和用户之间存在多对多关系,由
reviews
表表示。 Having a compound primary key based on two foreign keys lets you enforce referential integrity (a given tuple may only appear once), and at the same time provide a primary key for the table.拥有一个基于两个外键的复合主键可以让您强制执行参照完整性(给定的元组可能只出现一次),同时为表提供一个主键。
Another option would be to have a surrogate primary key for the bridge table.另一种选择是为桥表设置代理主键。 This could make things easier if you need to reference the
reviews
from another table, but you would still need a unique constraint on both foreign key columns for integrity, so this would actually result in extra space being used.如果您需要从另一个表中引用
reviews
,这可以使事情变得更容易,但是您仍然需要对两个外键列进行唯一约束以保持完整性,因此这实际上会导致使用额外的空间。
When it comes to your code, it has a few issues:当涉及到您的代码时,它有一些问题:
the primary key
keyword goes after the datatype primary key
关键字在数据类型之后
the check
constraint is incorrectly formed check
约束的格式不正确
missing or additional commas here and there此处和那里缺少或附加逗号
Consider:考虑:
CREATE TABLE users(
user_id SERIAL PRIMARY KEY ,
user_name VARCHAR NOT NULL UNIQUE,
pass_hash VARCHAR NOT NULL,
email VARCHAR NOT NULL UNIQUE
);
CREATE TABLE books(
book_id BIGINT PRIMARY KEY,
author VARCHAR NOT NULL,
title VARCHAR NOT NULL,
year INT NOT NULL CHECK (year > 1484),
review_count INT DEFAULT 0 NOT NULL,
avrg_score FLOAT
);
CREATE TABLE reviews(
user_id INT REFERENCES users(user_id) NOT NULL,
book_id INT REFERENCES books(book_id) NOT NULL,
score INT NOT NULL CHECK (score > 0 and score < 11),
PRIMARY KEY (book_id, user_id)
);
I the above is good but I would drop columns review_count and avrg_score from books.我上面的内容很好,但我会从书中删除列 review_count 和 avrg_score。 These are derivable when needed.
这些是在需要时可导出的。 If needed for your application then instead of storing these create a view to derive them.
如果您的应用程序需要,那么不要存储这些,而是创建一个视图来派生它们。 This avoids the always complicated process of maintaining running values:
这避免了维护运行值的复杂过程:
create view books_vw as
select b.book_id
, b.author
, b.title
, b.year
, count(r.*) review_count
, avg(r.score) avrg_score
from books b
left join reviews r
on r.book_id = b.book_id
group by
b.book_id
, b.author
, b.title
, b.year
;
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.