В связи с этот ответ я наткнулся на феномен, который я не могу объяснить.
Версия:
PostgreSQL 9.1.2 на x86_64-unknown-linux-gnu, скомпилированный gcc-4.4.real(Debian 4.4.5-8) 4.4.5, 64-разрядный
Рассмотрим следующую демонстрационную версию. Testbed:
CREATE TEMP TABLE t (
id integer
,txt text
,CONSTRAINT t_pkey PRIMARY KEY (id) DEFERRABLE INITIALLY IMMEDIATE
);
INSERT INTO t VALUES
(1, 'one')
,(2, 'two');
1) Оператор UPDATE, изменяющий несколько строк:
UPDATE t
SET id = t_old.id
FROM t t_old
WHERE (t.id, t_old.id) IN ((1,2), (2,1));
Кажется, в текущей реализации есть ошибка? Вышеупомянутое UPDATE работает, хотя не должно. Ограничение определено INITIALLY IMMEDIATE
, и я не использовал SET CONSTRAINTS
.
Я что-то упустил или это (довольно безобидная) ошибка?
2) Изменение данных CTE
Следовательно, данные, модифицирующие CTE, тоже работают, хотя с ошибкой NOT DEFERRED
pk:
WITH x AS (
UPDATE t SET id = 1 WHERE id = 2
)
UPDATE t SET id = 2 WHERE id = 1;
Я цитирую руководство по CTE:
Подзапросы в WITH выполняются одновременно друг с другом и с основным запросом. Поэтому при использовании модификации данных в WITH, порядок, в котором указанные обновления фактически произойдет непредсказуемо. Все утверждения выполняются с тем же моментальный снимок (см. главу 13), поэтому они не могут "видеть" эффекты друг друга на целевых таблицах.
3) Несколько операторов UPDATE в одной транзакции
Без SET CONSTRAINTS
это не выполняется с УНИКАЛЬНЫМ нарушением - как и ожидалось:
BEGIN;
-- SET CONSTRAINTS t_pkey DEFERRED;
UPDATE t SET id = 2 WHERE txt = 'one';
UPDATE t SET id = 1 WHERE txt = 'two';
COMMIT;