Спомням си, че повдигнах почти идентична точка, когато PG9 беше в алфа състояние. Ето отговора от Том Лейн (високопрофилен разработчик на PG ядро):
http://archives.postgresql.org/pgsql-general/2010-01/msg00221.php
Накратко:няма да се оправи.
Да не кажа, че съм съгласен с вашето предложение, че текущото поведение е грешка. Погледнете го от обратния ъгъл:това е поведението на NOT DEFERRABLE
това е неправилно.
Всъщност нарушението на ограничението в тази актуализация никога не трябва да се случва в никакъв случай, тъй като в края на актуализацията ограничението е удовлетворено. Състоянието в края на командата е това, което има значение. Междинните състояния по време на изпълнението на един оператор не трябва да бъдат изложени на потребителя.
Изглежда, че PostgreSQL прилага ограничението без отлагане, като проверява за дубликати след всеки актуализиран ред и се проваля веднага при първия дубликат, което по същество е дефектно. Но това е известен проблем, вероятно толкова стар, колкото PostgreSQL. В днешно време решението за това е точно да се използва ОТЛОЖЕНО ограничение. И има известна ирония в това, че го гледате като недостатъчен, защото не успява да се провали, докато по някакъв начин той трябва да бъде решението на провала на първо място!
Обобщение на статуквото след 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
не е опция, защото (според документация):
Референтните колони трябва да са колоните на неотлагаемо ограничение за уникален или първичен ключ в реферираната таблица.