Ограничение определено DEFERRABLE ИЗНАЧАЛЬНО НЕМЕДЛЕННО ОТЛОЖЕНО?

В связи сэтот ответЯ наткнулся на явление, которое не могу объяснить.

Версия:
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');

1) Оператор UPDATE, изменяющий несколько строк:

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.

Я что-то упустил или это (довольно безобидная) ошибка?


2) CTE, изменяющий данные

Следовательно, CTE, изменяющий данные, тоже работает, хотя и не работает с NOT DEFERREDpk:

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это завершается с ошибкой UNIQUE — как и ожидалось:

BEGIN;
-- SET CONSTRAINTS t_pkey DEFERRED;
UPDATE t SET id = 2 WHERE txt = 'one';
UPDATE t SET id = 1 WHERE txt = 'two';
COMMIT;

14
задан Community 23 May 2017 в 11:53
поделиться