Ответ 1
Я помню, что поднял почти идентичную точку, когда PG9 находился в альфа-состоянии. Здесь был ответ от Tom Lane (высококлассный разработчик PG): http://archives.postgresql.org/pgsql-general/2010-01/msg00221.php
Вкратце: не будет исправлено.
Нельзя сказать, что я согласен с вашим предложением о том, что текущее поведение является ошибкой. Посмотрите на него с противоположного угла: это неправильное поведение NOT DEFERRABLE
.
На самом деле, нарушение ограничения в этом UPDATE никогда не должно происходить в любом случае, так как в конце UPDATE ограничение выполняется. Состояние, стоящее в конце команды, имеет значение. Промежуточные состояния во время выполнения одного оператора не должны быть доступны пользователю.
Похоже, что PostgreSQL реализует не откладываемое ограничение, проверяя дубликаты после каждой обновленной строки и немедленно сбиваясь с первого дубликата, что по существу является недостатком. Но это известная проблема, вероятно, такая же старая, как PostgreSQL. В настоящее время обходным путем для этого является использование ограничения DEFERRABLE. И есть какая-то ирония в том, что вы смотрите на нее как на недостающую, потому что она не сработает, а как-то она должна быть решением проблемы в первую очередь!
Сводка статус-кво в PostgreSQL 9.1
- Ограничения
-
NOT DEFERRABLE
UNIQUE
илиPRIMARY KEY
проверяются после каждой строки. -
DEFERRABLE
ограничения, установленные наIMMEDIATE
(INITIALLY IMMEDIATE
или черезSET CONSTRAINTS
), проверяются после каждого утверждения. -
DEFERRABLE
ограничения, установленные наDEFERRED
(INITIALLY DEFERRED
или черезSET CONSTRAINTS
), проверяются после каждой транзакции.
Обратите внимание на специальную обработку ограничений UNIQUE
/PRIMARY KEY
.
Цитирование страницы руководства для CREATE TABLE
:
Ограничение, которое не откладывается, будет сразу проверено после каждой команды.
Пока он находится в разделе совместимости в разделе Non-deferred uniqueness constraints
:
Когда ограничение
UNIQUE
илиPRIMARY KEY
не откладывается, PostgreSQL проверяет уникальность сразу всякий раз, когда строка вставлена или модифицирована. В стандарте SQL говорится, что уникальность должна быть соблюдена только в конце инструкции; это имеет значение, когда для Например, одна команда обновляет несколько значений ключа. Чтобы получить стандартное поведение, объявите ограничение какDEFERRABLE
, но не откладывается (т.е.INITIALLY IMMEDIATE
). Имейте в виду, что это может быть значительно медленнее, чем немедленная проверка уникальности.
Смелый акцент мой.
Если вам нужны какие-либо ограничения FOREIGN KEY
для ссылки на столбец (столбцы), DEFERRABLE
не является опцией, потому что (для документации)
Указанные столбцы должны быть столбцами неотделяемой уникальной или ограничение первичного ключа в ссылочной таблице.