我想编写一个执行UPDATE的查询,如果结果行与约束匹配,则执行DELETE。
为了测试,我有下表:
# CREATE TABLE counts (id BIGSERIAL PRIMARY KEY, count BIGINT NOT NULL);
# INSERT INTO counts (count) VALUES (5), (1);
# SELECT * FROM counts;
id | count
----+-------
1 | 5
2 | 1
(2 rows)
现在,我编写了以下查询,从counts
表中减去一个count
,如果count
变为0,则删除该行:
WITH updated_counts AS (
UPDATE counts
SET count=count - 1
WHERE id=2
RETURNING *
)
DELETE FROM counts
USING updated_counts
WHERE counts.id=updated_counts.id
AND updated_counts.count=0;
在事务中运行此命令会更改counts
表,但不会删除行(返回的标记为DELETE 0
)。
# SELECT * FROM counts;
id | count
----+-------
1 | 5
2 | 0
(2 rows)
回滚这个事务并使用显示WITH子句结果的查询重试,我确实看到要删除的行具有正确的计数:
# WITH updated_counts AS (UPDATE counts
SET count=count - 1
WHERE id=2
RETURNING *
)
SELECT *
FROM updated_counts;
id | count
----+-------
2 | 0
(1 row)
以下查询也没有预期的结果:
# WITH updated_counts AS (UPDATE counts
SET count=count - 1
WHERE id=2
RETURNING *)
DELETE
FROM counts
WHERE id IN (SELECT id
FROM updated_counts
WHERE count=0
);
DELETE 0
# SELECT * FROM counts;
id | count
----+-------
1 | 5
2 | 0
(2 rows)
有人能解释一下为什么即使updated_counts
包含正确的行,DELETE
也没有删除它吗?理想情况下,如何修复查询以使其能够执行?
这是在Postgres服务器版本15.1,客户端版本14.7。
1条答案
按热度按时间m1m5dgzv1#
您不能在一条语句中**更新同一行两次。您可以分成两个语句或颠倒操作顺序。当你尝试更新一个不存在的行时,Postgres不会抛出错误。由于从列值中减去1,然后在结果为0时删除,这与删除初始值为1的列值是一样的,因此可以将
update
和delete
颠倒过来,先执行删除。所以: