根据另一个 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?
所以我有两个 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?