Выполняется только одно из двух UPDATE в CTE?

У меня возникла ситуация, когда мне приходится использовать CTE в этой форме.

WITH
update_field_a AS (
update super_table SET
  a = ....
WHERE condition to update a hold true
RETURNING TRUE
),
update_field_b AS (
update super_table SET
  b = ....
WHERE condition to update b hold true
RETURNING TRUE
)
SELECT 
  (SELECT true FROM update_field_a) as updated_a,
  (SELECT true FROM update_field_b) as updated_b,

Таким образом, в основном два CTE обновляют разные поля одной и той же таблицы, каждый из которых имеет свое собственное условие обновления в предложении WHERE.

Проблема в том, что поведение, которое я наблюдаю, заключается в том, что только CTE запускается в зависимости от того, какой из SELECT я вызываю первым в последнем запросе SELECT.

Это учитывая это

SELECT 
  (SELECT true FROM update_field_a) as updated_a, <-- first select
  (SELECT true FROM update_field_b) as updated_b,

update_field_a CTE будет запускаться и обновлять таблицу, в то время как update_field_b не запускается, поскольку (SELECT true FROM update_field_a) as updated_a вызывается первым.

Но если у меня есть:

SELECT 
  (SELECT true FROM update_field_b) as updated_b, <-- first select
  (SELECT true FROM update_field_a) as updated_a,

update_field_b CTE будет запускаться и обновлять таблицу, в то время как update_field_a не запускается, поскольку (SELECT true FROM update_field_a) as updated_a вызывается первым.

Как я могу обеспечить работу обоих CTE? Я думал, что ссылка на них в инструкции SELECT вызовет их оба, но по какой-то странной причине запускается только первая ссылка, которая получает ссылку.

Обратите внимание, что этот запрос является частью приложения Rust, использующего библиотеку sqlx. Обновление: я вижу такое же поведение, если запрос выполняется непосредственно в терминале psql, поэтому детали Rust/Sqlx не имеют никакого влияния.

🤔 А знаете ли вы, что...
SQL поддерживает сортировку данных с использованием оператора ORDER BY.


1
51
1

Ответ:

Решено

Все CTE и основной запрос видят один и тот же снимок базовых таблиц. Обновление одной и той же строки несколько раз не работает.

Как я могу обеспечить работу обоих CTE?

Вы не можете. Либо разделите запрос на два отдельных запроса, либо объедините оба обновления в одно. Нравиться:

UPDATE super_table
SET    a = CASE WHEN condition_a THEN ... ELSE a END
     , b = CASE WHEN condition_b THEN ... ELSE b END
WHERE (condition_a OR condition_b)
RETURNING condition_a AS updated_a
        , condition_b AS updated_b;

Связанный: