假设我有一个名为tPostgres 的表:
id | group_name | state
-----------------------------
1 | group1 | 0
2 | group1 | 0
3 | group1 | 0
Run Code Online (Sandbox Code Playgroud)
我需要state按 ID 更新行,同时还返回一些内容:
state= 0我有一个查询来执行此操作,如下所示:
UPDATE t AS updated SET state = 1
FROM t as original
WHERE
updated.id = original.id AND
updated.id = :some_id
RETURNING
updated.state AS new_state,
original.state AS old_state,
(
SELECT COUNT(*) FROM t
WHERE
group_name = updated.group_name AND
state = 0
) as remaining_count;
Run Code Online (Sandbox Code Playgroud)
然而,似乎其中的子查询是在更新完成之前RETURNING执行的,给我留下了 1 的值。remaining_count
此外,我不确定运行并发查询时它的行为如何。如果我们同时更新其中两行,它们是否有可能返回相同的结果remaining_count?
有更优雅的解决方案吗?也许某种窗口/聚合函数?
子查询确实在没有看到 的更改的情况下运行UPDATE,因为它是在UPDATE提交之前运行的,因此它是不可见的。不过,这是一个简单的解决方法;只需添加一个 where 子句来过滤掉您刚刚在子查询中更新的 ID,使您的查询如下所示:
UPDATE t AS updated SET state = 1
FROM t as original
WHERE
updated.id = original.id AND
updated.id = :some_id
RETURNING
updated.state AS new_state,
original.state AS old_state,
(
SELECT COUNT(*) FROM t
WHERE
group_name = updated.group_name AND
state = 0 AND
t.id <> :some_id /* this is what I changed */
) as remaining_count;
Run Code Online (Sandbox Code Playgroud)
就并发而言,我不确定行为会是什么,TBH;我能做的就是向您指出相关文档。