根据另一个 table 的值更新行?

Updating a row based on a value from another table?

所以我有两个 table 的“books”和“bookOrder”,它们看起来像这样:

bookOrder

| orderID | book name   | required | availability
| --------|-------------| ---------| ------------|
| 1       |Harry Potter | 9        | yes         |
| 2       |Twilight     | 8        | yes         |
| 3       |Bible        | 8        | yes         |

books

|book name   |quantity|
|------------|--------|
|Harry Potter|10      |
|Twilight    |5       |
|Bible       |8       |

我希望能够根据“书籍”更新“bookOrder”可用性列table。

到目前为止,我的 SQL 查询如下:

UPDATE bookOrder
SET avalability = case when (
SELECT quantity
FROM books
WHERE books.bookName = bookOrder.bookName
) < (SELECT required From bookOrder WHERE bookOrder.bookName = books.bookName) THEN 'NO' END;

但是我得到一个错误:

missing FROM-clause entry for table "books"

我的查询可能完全错了。

(P.S。我知道有人想买 8 本暮光之城的书是完全荒谬的。)

我会在这里使用更新连接:

UPDATE bookOrder bo
SET availability = CASE WHEN b.quantity < bo.required THEN 'NO' ELSE 'YES' END
FROM books b
WHERE b.bookName = bo.bookName

使用UPDATE syntax as ,但再添加一个WHERE条件:

UPDATE bookOrder bo
SET    availability = CASE WHEN b.quantity < bo.required THEN 'NO' ELSE 'YES' END
FROM   books b
WHERE  b.bookName = bo.bookName
AND    bo.availability IS DISTINCT FROM CASE WHEN b.quantity < bo.required THEN 'NO' ELSE 'YES' END;

这样,Postgres 只会写入一个新的行版本,其中值实际发生了变化。这会对写入性能和一般数据库性能产生重大影响。参见:

  • How do I (or can I) SELECT DISTINCT on multiple columns?

availability实际上应该是数据类型boolean,在这种情况下你可以简化:

UPDATE bookOrder bo
SET    availability = (b.quantity >= bo.required)
FROM   books b
WHERE  b.bookName = bo.bookName
AND    bo.availability IS DISTINCT FROM (b.quantity >= bo.required);

如果使用 FK 约束强制执行参照完整性并且定义了所有涉及的列NOT NULL,请进一步简化:

...
AND    bo.availability <> (b.quantity >= bo.required);

完全删除该列并动态查找 availability。这样的属性在到达时可能已过时。您可以为此使用 VIEW

CREATE VIEW book_order_plus AS
SELECT bo.*, (b.quantity >= bo.required) AS availability
FROM   bookOrder bo
LEFT   JOIN books b USING (bookName);

哦,使用合法的、小写的、不带引号的标识符让您的 Postgres 生活变得简单。参见:

  • Are PostgreSQL column names case-sensitive?