5

我正在构建一个简单的库应用程序。我有一张叫书的桌子;它的列包括:

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 表中没有数据,我不能简单地输入一个(所有空值等),无论如何我仍然需要获取所有作者 ID 并将它们插入正确的行。

如何根据匹配现有列中的值将正确的 author_ids 插入到 books 表中?我试过了:

insert into books (author_id) select author_id from authors where (books.author == authors.author_name);

但可以预见的是,这太天真了。

4

2 回答 2

11

您可以在语句中加入其他表UPDATE,允许使用这种更可取的形式:

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

三个原因:

  • 它更安全。您的查询将在找不到匹配作者的每一行中写入一个 NULL 值。在您的情况下,这并不重要,但可能会导致类似查询中的数据丢失,您已经在列中有要更新的数据。如果找不到匹配的作者,我的替代方案什么也不做。

  • 它更快。以上为一。但也因为像你这样的相关子查询的规模非常大。加入表通常更快,尤其是在多行的情况下。

  • 它更干净,更容易适应额外的列。

于 2013-06-17T23:44:07.667 回答
2

whelp,搞砸了,我已经设法回答了我自己的问题。首先,它应该是一个更新(duh);第二:

update books set author_id = (select author_id from authors where books.author = authors.author_name);
于 2013-06-14T23:27:30.810 回答