Ik herinner me dat ik een bijna identiek punt naar voren had gebracht toen PG9 zich in de alpha-status bevond. Hier was het antwoord van Tom Lane (bekende PG-kernontwikkelaar):
http://archives.postgresql.org/pgsql-general/2010-01/msg00221.php
Kortom:lost niet op.
Om niet te zeggen dat ik het eens ben met uw suggestie dat het huidige gedrag een bug is. Bekijk het vanuit de tegenovergestelde hoek:het is het gedrag van NOT DEFERRABLE
dat is onjuist.
In feite zou de schending van de beperking in deze UPDATE in geen geval mogen gebeuren, omdat aan het einde van de UPDATE aan de beperking is voldaan. De status aan het einde van het commando is waar het om gaat. De tussenliggende toestanden tijdens de uitvoering van een enkele instructie mogen niet aan de gebruiker worden getoond.
Het lijkt erop dat de PostgreSQL de niet-uitstelbare beperking implementeert door te controleren op duplicaten na elke bijgewerkte rij en onmiddellijk faalt bij het eerste duplicaat, wat in wezen gebrekkig is. Maar dit is een bekend probleem, waarschijnlijk zo oud als PostgreSQL. Tegenwoordig is de oplossing hiervoor juist het gebruik van een DEFERRABLE-beperking. En het is ironisch dat je het als gebrekkig beschouwt omdat het niet faalt, terwijl het op de een of andere manier de oplossing voor het falen zou moeten zijn!
Samenvatting van de status-quo sinds PostgreSQL 9.1
-
NOT DEFERRABLE
UNIQUE
ofPRIMARY KEY
beperkingen worden gecontroleerd na elke rij . -
DEFERRABLE
beperkingen ingesteld opIMMEDIATE
(INITIALLY IMMEDIATE
of viaSET CONSTRAINTS
) worden na elke stelling aangevinkt . -
DEFERRABLE
beperkingen ingesteld opDEFERRABLE
(INITIALLY DEFERRED
of viaSET CONSTRAINTS
) worden gecontroleerd na elke transactie .
Let op de speciale behandeling van UNIQUE
/ PRIMARY KEY
constraints. Citaat van de handleiding voor CREATE TABLE
:
Een beperking die niet uitstelbaar is, wordt na elk commando onmiddellijk gecontroleerd .
Terwijl het verderop in de Compatibiliteit . staat sectie onder Non-deferred uniqueness constraints
:
Wanneer een
UNIQUE
ofPRIMARY KEY
beperking is niet uitstelbaar, PostgreSQL controleert onmiddellijk op uniciteit telkens wanneer een rij wordt ingevoegd of gewijzigd. De SQL-standaard zegt dat uniciteit alleen aan het einde van de instructie . moet worden afgedwongen; dit maakt een verschil wanneer bijvoorbeeld een enkele opdracht meerdere sleutelwaarden bijwerkt. Om normconform gedrag te verkrijgen, verklaart u de beperking alsDEFERRABLE
maar niet uitgesteld (d.w.z.INITIALLY IMMEDIATE
). Houd er rekening mee dat dit aanzienlijk langzamer kan zijn dan onmiddellijke uniciteitscontrole.
Vetgedrukte nadruk van mij.
Als u een FOREIGN KEY
. nodig heeft beperkingen om te verwijzen naar de kolom(men), DEFERRABLE
is geen optie omdat (volgens documentatie):
De kolommen waarnaar wordt verwezen, moeten de kolommen zijn van een niet-uitstelbare unieke of primaire sleutelbeperking in de tabel waarnaar wordt verwezen.