postgresql - 使用 EXCEPT 集合运算符时如何编写 Postgres SELECT FOR UPDATE?

标签 postgresql select locking

在 Postgres(11,如果重要的话)中,我需要执行 SELECT FOR UPDATE 来获取行集合,我随后将对其进行一些更改,但我不这样做'当我进行这些更改时,我不希望交易之外的任何人乱搞。

但是,我想要锁定的行集实际上是由集合差异定义的,即,

SELECT <columns> FROM table1 t1 JOIN table2 t2 ON ... WHERE ...
EXCEPT
SELECT <columns> FROM table1 t1 JOIN table3 t3 ON ... WHERE ...

我想要这个集合差异的结果集来确定被锁定的行集;也就是说,理想情况下,第二个 SELECT 选择的行不应被锁定。

但我不太确定在哪里放置 FOR UPDATE 子句来实现此目的。似乎将 FOR UPDATE 立即放在上面的任何 SELECT 行之后不会给我我想要的东西。事实上,我怀疑我不能合法地将它放在第一行SELECT之后(即,就在EXCEPT之前)。

我想到的一个想法是将第二个 SELECT(即 EXCEPT 的主题)加上括号,以便 FOR UPDATE code> 不会被解释为第二个 SELECT 的一部分:

SELECT <columns> FROM table1 t1 JOIN table2 t2 ON ... WHERE ...
EXCEPT
(SELECT <columns> FROM table1 t1 JOIN table3 t3 ON ... WHERE ...)
FOR UPDATE

但我也不确定这是否能给我想要的东西,即使它在语法上是可以接受的。

如果我知道(Postgres)select 语句的解析树的形状,我可能可以轻松地自己弄清楚;但事实上,我现在有点迷失了。

最佳答案

您不能将 FOR UPDATEUNIONINTERSECTEXCEPT 一起使用,因为这可能会导致歧义一般情况。

我可以想到两种方法:

  1. 使用EXISTSNOT EXISTS:

    SELECT ... FROM table1
    WHERE EXISTS (SELECT 1 FROM table2 ...
                  WHERE table2.x = table1.x AND ...)
      AND NOT EXISTS (SELECT 1 FROM table3 ...
                      WHERE table3.y = table1.y AND ...)
    FOR UPDATE OF table1;
    
  2. 使用子查询:

    SELECT ... FROM table1
    WHERE id IN (SELECT t1.id
                 FROM table1 t1 JOIN table2 t2 ON ...
                 WHERE ...
                 EXCEPT
                 SELECT t1.id
                 FROM table1 t1 JOIN table3 t3 ON ...
                 WHERE ...)
    FOR UPDATE OF table1;
    

关于postgresql - 使用 EXCEPT 集合运算符时如何编写 Postgres SELECT FOR UPDATE?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/65365653/

相关文章:

c++ - 这个锁的内存屏障是否正确?

MySQL:GET_LOCK 限制和问题

SQL:如何获得本科和研究生学位的类(class)?

xml - 在 PostgreSQL 中从文件插入 XML

php - mySQL - 使用 JOIN 或嵌套 SELECT(子选择)进行选择?

javascript - 如何在加载的页面上创建多个 select-2

c# - 锁定导致数据库操作太慢

postgresql - 删除用户后尝试访问 psql 但仍被要求输入已删除用户的密码

oracle - ORA-00907 缺少右括号 Postgresql 到 Oracle

mysql - 统计每个年龄段的记录数