在Postgres 13中,我有一个经常更新的表。但是,更新查询相当复杂,多次使用相同的值。因此,使用CTE似乎是一件非常合乎逻辑的事情。
一个简化的示例如下所示:
WITH my_cte AS (
SELECT
my_id,
CASE WHEN my_value1 > 100 THEN 50 ELSE 10 END AS my_addition
FROM my_table
WHERE my_id = $1
)
UPDATE my_table
SET my_value1 = my_table.my_value1 + my_cte.my_addition,
my_value2 = my_table.my_value2 + my_cte.my_addition
FROM my_cte
WHERE my_table.my_id = my_cte.my_id现在我想知道:如果在CTE中的SELECT和UPDATE之间,表由另一个查询更新,从而更改my_value1,那么当UPDATE发生时,my_addition的计算就会变得过时和错误。会否出现这种情况呢?或者Postgres是否自动设置隐式锁?
如果Postgres在这里没有魔法,我需要自己来处理:在CTE的FOR UPDATE中做SELECT就足够了吗?
对不起,如果我在这里没有说清楚:我并不想“看到”那些并发修改,我想阻止它们--即,一旦完成了SELECT的计算,在UPDATE完成之前,其他任何查询都不会修改这一行。
在现实生活中,我在CASE WHEN my_value1 > 100 THEN 50 ELSE 10 END中嘲笑的东西大约有20行长,我需要在UPDATE中的大约5个地方使用它。因为我是“不要重复自己”的忠实粉丝,所以我认为CTE是可行的。或者,是否有更好的方法来避免在没有CTE的UPDATE中复制和粘贴?
发布于 2022-03-14 20:10:38
如果要防止并发语句在更新前修改CTE选择的行,则需要在CTE中使用SELECT ... FOR NO KEY UPDATE。
https://dba.stackexchange.com/questions/308688
复制相似问题