В связи сэтот ответЯ наткнулся на явление, которое не могу объяснить.
Версия:
PostgreSQL 9.1.2 на x86_64-unknown-linux-gnu, скомпилированный gcc-4.4.real (Debian 4.4.5-8) 4.4.5, 64-бит
Рассмотрим следующую демонстрацию. Тестовый стенд:
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');
UPDATE t
SET id = t_old.id
FROM t t_old
WHERE (t.id, t_old.id) IN ((1,2), (2,1));
Кажется, в текущей реализации есть ошибка? Приведенное выше ОБНОВЛЕНИЕ работает, хотя не должно. Ограничение определено INITIALLY IMMEDIATE
, и я не использовал SET CONSTRAINTS
.
Я что-то упустил или это (довольно безобидная) ошибка?
Следовательно, 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), поэтому они не могут «видеть» эффекты друг друга на целевых столах.
Без SET CONSTRAINTS
это завершается с ошибкой UNIQUE — как и ожидалось:
BEGIN;
-- SET CONSTRAINTS t_pkey DEFERRED;
UPDATE t SET id = 2 WHERE txt = 'one';
UPDATE t SET id = 1 WHERE txt = 'two';
COMMIT;