Sql 一列中有许多外键
我在Postgres中有一个图书数据库,我想添加一个authorId列,但当一本书有许多作者时,我不知道如何使它工作 作者表Sql 一列中有许多外键,sql,postgresql,select,Sql,Postgresql,Select,我在Postgres中有一个图书数据库,我想添加一个authorId列,但当一本书有许多作者时,我不知道如何使它工作 作者表 authorId firstName lastName 1 Terry Pratchett 2 Neil Gaiman 书桌 bookId name authorId 1 Good Omens 1, 2 我如何让它工作?我的第一个
authorId firstName lastName
1 Terry Pratchett
2 Neil Gaiman
书桌
bookId name authorId
1 Good Omens 1, 2
我如何让它工作?我的第一个想法是将authorId存储为数组
我想要的查询应该是这样的
SELECT firstName, lastName
FROM author
WHERE authorId IN
(SELECT authorId
FROM book
WHERE bookId=1);
它会返回这个
firstName lastName
Terry Pratchett
Neil Gaiman
但我有一种感觉,这是行不通的,有一种更好的方法可以做到。m:n关系(一个作者可以写很多书+一本书可以由很多作者写)最好用桥牌表来建模:
- 作者(作者id、名、姓)
- 书(书号、书名)
- 图书作者(图书id,作者id)
教科书上的解决方案将是有一个额外的“映射”表来映射书籍和作者。这样一来,一位作者可能会写几本书,而一本书可能会有几位作者:
CREATE TABLE book_authors (
author_id INT NOT NULL,
book_id INT NOT NULL,
PRIMARY KEY book_authors_pk (author_id, book_id),
FOREIGN KEY author_fk (author_id) REFERENCES authors (author_id),
FOREIGN KEY book_fk (book_id) REFERENCES books (book_id)
)
然后,您可以使用join
查询书籍的作者:
SELECT first_name, last_name
FROM authors a
JOIN book_authors ba on a.author_id = ba.author_id
WHERE book_id = 1
或者,如果您没有该书的id,另一个与books
的连接将允许您查询其详细信息:
SELECT first_name, last_name
FROM authors a
JOIN book_authors ba ON a.author_id = ba.author_id
JOIN books b ON ba.book_id = b.book_id
WHERE b.name = 'Good Omens'
是的,使用postgres这一事实为您提供了将Authorid存储为数组的绝佳选择。您可以按如下方式定义表:
CREATE TABLE Book (
bookId serial not null,
name varchar,
authorIds int[]
);
您的select查询应该是
SELECT firstName, lastName
FROM author
WHERE authorId IN
(SELECT unnest(authorIds)
FROM Book
WHERE bookId = 1);
那是个可怕的主意。您应该了解规范化我不认为这是一个可怕的想法,规范化并不总是实践中的最佳选择(增加冗余、管理更多的表、更多的连接、较差的性能等等),这就是为什么Postgres有一种广泛用于industry@pedram巴希里:你错了。规范化从不增加冗余,因为规范化的主要目的是减少冗余。它还增加了一致性(在本例中,它保证只将书籍链接到现有的作者ID)。最后但并非最不重要的是:它增加了速度。使用桥接表查找书籍的作者通常非常快(提供了适当的索引),而数组方法往往非常慢,因为在表中查找书籍ID的唯一方法是读取所有记录。@pedram bashiri:至于冗余:是的。我看不出桥接表在哪里增加了任何冗余。没有。至于规范化:数据库应该规范化。然而,数组不一定违反规范化。当您将某个内容存储为字符串时,您不应该对DBMS中的子字符串感兴趣(那么您应该单独存储子字符串)。数组也是如此:当你存储一个数组时,你不应该对该数组的单个元素感兴趣…@pedram bashiri:。。。在本例中,我们对单数组元素非常感兴趣,因为它们甚至是ID。在数组中存储ID不是一个好主意,因为这可能导致不一致。如果你想存储,比如说,备忘录或者类似的东西,数组可以非常方便。至于这个行业:我已经在相当大的数据库(超过1000个表)工作了25年多,我在这里和那里看到了违反规范的情况。这通常是有代价的。
SELECT firstName, lastName
FROM author
WHERE authorId IN
(SELECT unnest(authorIds)
FROM Book
WHERE bookId = 1);