Подтвердить что ты не робот

PostgreSql → CTE + UPDATE + DELETE → ожидаемый результат, почему?

Просто интересно, почему ниже (упрощенный) пример работает таким образом.

CREATE TABLE test (id SERIAL, val INT NOT NULL, PRIMARY KEY(id));
INSERT INTO test (val) VALUES (1);

WITH t AS ( UPDATE test SET val = 1 RETURNING id ) 
DELETE FROM test WHERE id IN ( SELECT id FROM t);

Результат:
УДАЛИТЬ 0

Вопрос:
Почему DELETE не нашел ни одной строки для удаления?

PostgreSql версия 9.2.1
Выделение транзакции = прочитанное сообщение

Спасибо!

4b9b3361

Ответ 1

Я подозреваю, что это имеет какое-то отношение к этой строке в docs -

Основной запрос и запросы WITH выполняются (по существу) в то же время. Это означает, что последствия изменения данных утверждение в WITH не видно из других частей запроса, другое чем путем считывания вывода RETURNING. Если два таких модифицирующих данных операторы пытаются изменить одну и ту же строку, результаты не определено.

Хотя я бы подумал, что идентификатор будет доступен, поскольку он не изменяется в подзапросе WITH, может быть что-то происходит с видимостью строки. Термин "неуказанный" довольно расплывчатый, это действительно может быть вопросом для списка postgres, так что один из гуру может иметь трещину в нем...

EDIT: чтобы предоставить немного больше информации, я также попытался заменить DELETE на SELECT *, и это вернуло ожидаемые строки. Моя немедленная реакция заключалась в том, что если он сможет найти строки для их возвращения, он должен будет найти их для их удаления. Но если я думаю об этом больше, этот тест поддерживает цитату, поскольку выражение о модификации данных в паре с оператором, не изменяющим данные, приводит к ожидаемым результатам, тогда как два оператора, изменяющих данные, создают неожиданные результаты.