UNION ALL vs UNION для обновления/возврата + выбор?

Я пытаюсь сделать запрос идемпотентным, помечая строки как обновленные. Однако часть спецификации запроса заключается в том, чтобы возвращать идентификаторы строк, соответствующих фильтру. Я думал сделать что-то вроде следующего:

WITH
prev as (
     SELECT id
       FROM books
      WHERE id = any($1::uuid[])
        AND updated
),
updated as (
     UPDATE books
        SET author = $2 || author, updated = true
      WHERE id = any($1::uuid[])
        AND not updated
  RETURNING id
)
SELECT id FROM prev
UNION ALL
SELECT id FROM updated

Я надеюсь избежать шага дедупликации при использовании UNION вместо UNION ALL, поэтому мне было интересно, гарантирует ли семантика оператора, что 1-й запрос не видит результаты 2-го.

Похожие вопросы:


person Felipe    schedule 07.12.2019    source источник


Ответы (1)


В документах PostgreSQL указано, что два CTE будут выполняться одновременно и в одном и том же моментальном снимке, поэтому UNION ALL безопасно использовать.

Подоператоры в WITH выполняются одновременно друг с другом и с основным запросом. Таким образом, при использовании операторов, изменяющих данные, в WITH порядок, в котором на самом деле происходят указанные обновления, непредсказуем. Все операторы выполняются с одним и тем же моментальным снимком (см. главу 13), поэтому они не могут «видеть» влияние друг друга на целевые таблицы. Это смягчает последствия непредсказуемости фактического порядка обновления строк и означает, что ВОЗВРАТ данных — единственный способ сообщить об изменениях между различными подоператорами WITH и основным запросом.

person Felipe    schedule 07.12.2019