如何通过匹配值从另一个表插入到表格中?

5

我正在构建一个简单的图书馆应用程序。我有一个名为books的表,其中包含以下列:

books:
book_id   | integer | not null default nextval('books_book_id_seq'::regclass)
title     | text    | not null
author    | text    | not null default 'unknown'::text

我原本没有计划对作者做任何特别的处理,因为我只关心他们的名字(所以没有联结表、作者表等)。但是现在,我发现按作者查找书籍的API端点需要某种作者ID:

/browse/author/12345

替代

/browse/author/Arthur%20C%20Clarke (or whatever)

我为作者创建了一个单独的表:

authors:
author_id   | integer | not null default nextval('authors_author_id_seq'::regclass)
author_name | text    | not null

需要通过id列将每一本书的行与其作者关联起来。我知道我需要一个外键,但由于books表中没有数据,我不能简单地插入一个(所有值都为null等),而且无论如何,我仍然需要获取所有作者id并将它们插入到正确的行中。
如何根据匹配现有列中的值将正确的作者id插入到books表中?我尝试过:
insert into books (author_id) select author_id from authors where (books.author == authors.author_name);

但可以预料的是,那太天真了。

2个回答

11

您可以在UPDATE语句中加入附加表,从而实现更优先的形式:

UPDATE books b
SET    author_id = a.author_id
FROM   authors a
WHERE  b.author = a.author_name;

三个原因:

  • 更安全。您的查询将在未找到匹配作者的每一行中写入NULL值。这在您的情况下似乎无关紧要,但在类似的查询中可能会导致数据丢失,其中您已经拥有要更新的列中的数据。如果未找到匹配的作者,我的替代方案不会执行任何操作。

  • 更快。上面是一个例子。但是,像您拥有的相关子查询会随着规模的扩大而变得非常缓慢。加入表通常比使用多行更快。

  • 更清晰,更容易适应其他列。


我现在没有尝试的必要,但它看起来很棒!谢谢! - whiterook6

2

嗯,我在折腾中解决了自己的问题。首先,它应该是一个更新(显然);其次:

update books set author_id = (select author_id from authors where books.author = authors.author_name);

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接