Sql 多个外键作为主键Postgre,我应该这样做吗?
这就是其中之一:为什么我应该或者为什么我不应该 所以我的图书应用程序有评论,但是一个用户不能对同一本书评论超过一次。在我看来,为评论创建一个表并将用户id和图书id(ISBN)作为评论表的主键是有意义的。但是,如果应用程序得到太多的评论,在某一点上可能会有问题吗?例如,这个决定会减缓查询速度吗 我正在使用postgres,我不确定以下代码是否正确:Sql 多个外键作为主键Postgre,我应该这样做吗?,sql,database,postgresql,foreign-keys,primary-key,Sql,Database,Postgresql,Foreign Keys,Primary Key,这就是其中之一:为什么我应该或者为什么我不应该 所以我的图书应用程序有评论,但是一个用户不能对同一本书评论超过一次。在我看来,为评论创建一个表并将用户id和图书id(ISBN)作为评论表的主键是有意义的。但是,如果应用程序得到太多的评论,在某一点上可能会有问题吗?例如,这个决定会减缓查询速度吗 我正在使用postgres,我不确定以下代码是否正确: CREATE TABLE users( user_id PRIMARY KEY SERIAL, user_name VARCHAR
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)
);
创建表用户(
用户id主键序列号,
用户名VARCHAR非空唯一,
pass_hash VARCHAR不为空,
电子邮件VARCHAR NOT NULL UNIQUE,
);
创建桌面书(
book_id主键BIGINT,
作者VARCHAR不为空,
title VARCHAR不为空,
年份INT非空检查(年份>1484),
review_count INT默认值0不为空,
avrg_分数浮动,
);
创建表评论(
user\u id INT外键引用用户(user\u id)不为NULL
book_id INT外键参考书籍(book_id)不为空
分数整数非空检查(分数>0,分数<11)
主键(图书id、用户id)
);
这是一个非常有效的设计选择
书籍和用户之间存在多对多关系,这一关系由reviews
表表示。使用基于两个外键的复合主键可以强制引用完整性(给定元组只能出现一次),同时为表提供主键
另一种选择是为桥接表提供代理主键。如果您需要从另一个表中引用审阅
,这会使事情变得更容易,但是您仍然需要在两个外键列上都有一个唯一的完整性约束,因此这实际上会导致使用额外的空间
当涉及到您的代码时,它有几个问题:
关键字位于数据类型之后主键
约束的格式不正确检查
- 此处和此处缺少或添加逗号
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)
);
创建表用户(
用户id串行主键,
用户名VARCHAR非空唯一,
pass_hash VARCHAR不为空,
电子邮件VARCHAR非空唯一
);
创建桌面书(
book_id BIGINT主键,
作者VARCHAR不为空,
title VARCHAR不为空,
年份INT非空检查(年份>1484),
review_count INT默认值0不为空,
avrg_分数浮动
);
创建表评论(
user\u id INT引用的用户(user\u id)不为NULL,
图书id INT参考图书(图书id)不为空,
分数INT非空检查(分数>0且分数<11),
主键(图书id、用户id)
);
I上面的内容很好,但我会从书中删除列review\u count和avrg\u score。当需要时,这些是可衍生的。如果应用程序需要,则创建一个视图来派生它们,而不是存储它们。这避免了维护运行值的复杂过程:
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
;
谢谢,这真的很有启发性=道指,很好的观点,我在获取数据时没有考虑这个问题。我认为这很有意义,因为数据库的工作会更好。谢谢大家!=D