首页 > 解决方案 > Postgres:使用 CTE 选择更新

问题描述

我总是有以下形式的查询:

UPDATE 
  users 
SET 
  col = 1 
WHERE 
  user_id IN ( 
    SELECT 
      user_id 
    FROM 
      users 
    WHERE 
      ... 
    LIMIT 1
    FOR UPDATE 
  );

而且我很确定它会在受影响的行上生成一个锁,直到更新完成。

现在我使用 CTE 编写了相同的查询并执行

WITH query AS (
  select 
    user_id 
  FROM 
    users 
  WHERE 
    ... 
  LIMIT 1 
  FOR UPDATE 
)
UPDATE 
  users 
SET 
  col = 1 
WHERE 
  user_id IN ( 
    SELECT 
      user_id 
    FROM 
      query 
  );

由于我得到的结果,我实际上怀疑它是否正在应用行锁,但我找不到任何关于此的记录。

有人可以说清楚吗?谢谢

编辑:

我设法找到了这个:

如果在 FOR UPDATE 或 FOR SHARE 中命名了特定的表,那么只有来自这些表的行被锁定;SELECT 中使用的任何其他表都照常读取。没有表列表的 FOR UPDATE 或 FOR SHARE 子句会影响语句中使用的所有表。如果将 FOR UPDATE 或 FOR SHARE 应用于视图或子查询,它会影响视图或子查询中使用的所有表。但是,FOR UPDATE/FOR SHARE 不适用于主查询引用的 WITH 查询。如果您希望在 WITH 查询中发生行锁定,请在 WITH 查询中指定 FOR UPDATE 或 FOR SHARE。

https://www.postgresql.org/docs/9.0/sql-select.html#SQL-FOR-UPDATE-SHARE

所以我想只有当for更新在with中而不是在使用with的查询中时它才应该起作用?

标签: sqlpostgresqlcommon-table-expression

解决方案


推荐阅读