多个外键作为主键postgres,我应该这样做吗?

slwdgvem  于 2021-08-09  发布在  Java
关注(0)|答案(2)|浏览(378)

这就是其中之一:为什么我应该或者为什么我不应该。
所以我的图书应用程序有评论,但一个用户不能评论同一本书超过一次。在我看来,为评论创建一个表并将用户id和图书id(isbn)作为评论表的主键是有意义的。但是,如果应用程序得到太多的评论,在某个时候会有问题吗?例如,这个决定会减慢查询速度吗?
我正在使用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)

);
vsnjm48y

vsnjm48y1#

这是一个非常有效的设计选择。
在书籍和用户之间有一种多对多的关系,这种关系由 reviews table。使用基于两个外键的复合主键可以强制执行引用完整性(给定的元组只能出现一次),同时为表提供主键。
另一种选择是为桥表提供一个代理主键。如果您需要引用 reviews 但是您仍然需要对两个外键列都有一个唯一的约束来保证完整性,所以这实际上会导致使用额外的空间。
在代码方面,它有几个问题:
这个 primary key 关键字在数据类型之后
这个 check 约束格式不正确
此处和此处缺少或添加逗号
考虑:

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)

);
gmxoilav

gmxoilav2#

我认为以上是好的,但我会删除列审查\ u计数和avrg\ u分数从书籍。当需要时,这些都是可导出的。如果应用程序需要,则创建一个视图来派生它们,而不是存储它们。这避免了维护运行值的复杂过程:

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                  
 ;

相关问题