У меня возникла ситуация, когда мне приходится использовать 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.
Все 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;
Связанный: