Особый случай обновления столбца с ненулевыми и уникальными ограничениями в PostgreSQL - PullRequest
1 голос
/ 21 июля 2010

Это игрушечный пример, который иллюстрирует реальную проблему в PostgreSQL. Приведенные ниже примеры используют сервер PostgreSQL 8.4.3, но я подозреваю, что другие версии имеют ту же проблему.

С учетом следующей таблицы:

=> create table tmp_foo (foo boolean not null unique, bar boolean not null unique);
=> insert into tmp_foo (foo, bar) values (true, true), (false, false);
=> select * from tmp_foo;
 foo | bar 
-----+-----
 t   | t
 f   | f

можно ли изменить таблицу так:

=> select * from tmp_foo;
 foo | bar 
-----+-----
 t   | f
 f   | t

без удаления строк или изменения схемы таблицы? Это:

=> update tmp_foo set bar = not bar;
ERROR:  duplicate key value violates unique constraint "tmp_foo_bar_key"

не работает.

Если удаление разрешено, это:

=> create temp table tmp_foo_2 as select * from tmp_foo;
=> update tmp_foo_2 set bar = not bar;
=> delete from tmp_foo;
=> insert into tmp_foo select * from tmp_foo_2;

работает. Это не самое простое решение для этого примера, но его легко обобщить на более сложные примеры.

1 Ответ

3 голосов
/ 21 июля 2010

Для этого требуются отложенные уникальные ограничения.

У нас столько строк, сколько возможно уникальных значений в каждом столбце. Таким образом, чтобы изменить любую строку, либо некоторые строки должны временно нарушать уникальное ограничение, либо некоторые строки должны быть удалены, чтобы избежать нарушения ограничения. Отложенные уникальные ограничения позволяют нам делать первое - временное нарушение (внутри транзакции).

Если вы идете так далеко, и это звучит правильно, то ответ на ваш вопрос зависит от версии Postgres.

Только Postgres до 8.4 позволяет отложить ограничения внешнего ключа . Следствием этого является то, что уникальные ограничения не могут быть отложены.

Бета-версии Postgres 9.0 теоретически предлагают отсроченные уникальные ограничения. Я сам не пробовал, но эта функция появилась очень долго, поэтому готов поспорить, что они правильно поняли, когда решили ее реализовать.

Вот два примера соответствующей документации по уникальным индексам 9.0 и SET CONSTRAINTS. Как видно из последней ссылки, уникальные ограничения явно перечислены как поддерживаемые для отсрочки через SET CONSTRAINTS в документации 9.0. Я еще не исследовал эту новую функцию и не могу гарантировать, что семантика именно то, что вам нужно. Но, похоже, просто вещь.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...