【发布时间】:2018-08-05 19:28:32
【问题描述】:
我在 Postgres 中有一个书籍数据库,我想添加一个 authorId 列,但是当一本书有很多作者时,我不知道如何使它工作。
作者表
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
但我有一种感觉,它不会起作用,并且有更好的方法来做到这一点。
【问题讨论】:
-
这是一个可怕的想法。您应该了解规范化
-
我不认为这是一个可怕的想法,规范化在实践中并不总是最好的选择(增加冗余、更多要管理的表、更多连接、性能差……),这是为什么 Postgres 有数组这种数据类型在工业中被广泛使用
-
@pedram bashiri:你错了。规范化从不增加冗余,因为规范化的主要目的是减少冗余。并且它还增加了一致性(在这个例子中,它保证您只将书籍链接到现有的作者 ID)。最后但同样重要的是:它增加了速度。使用桥接表查找书籍的作者通常非常快(提供了适当的索引),而数组方法往往非常慢,因为在表中查找书籍 ID 的唯一方法是读取所有记录。跨度>
-
@pedram bashiri:关于冗余:是的。我看不到桥接表在哪里增加了任何冗余。它没有。至于规范化:数据库应该被规范化。但是,数组不一定违反规范化。当您将某些内容存储为字符串时,您不应该对 DBMS 中的子字符串感兴趣(那么您应该单独存储子字符串)。数组也是一样:当你存储一个数组时,你不应该对该数组的单个元素感兴趣......
-
@pedram bashiri: ...在这个例子中,我们对单个数组元素非常感兴趣,因为它们甚至是 ID。将 ID 存储在数组中并不是一个好主意,因为这会导致不一致。但是,如果您想存储备忘录或类似内容,则数组可以非常方便。至于行业:我在相当大的数据库(超过一千个表)上工作了超过 25 年,我看到这里和那里都违反了规范化。这通常是有代价的。
标签: sql postgresql select