Jeg husker at have rejst et næsten identisk punkt, da PG9 var i alfatilstand. Her var svaret fra Tom Lane (højprofileret PG-kerneudvikler):
http://archives.postgresql.org/pgsql-general/2010-01/msg00221.php
Kort sagt:vil ikke løse.
For ikke at sige, at jeg er enig i dit forslag om, at den nuværende adfærd er en fejl. Se på det fra den modsatte vinkel:det er adfærden hos NOT DEFERRABLE
det er forkert.
Faktisk bør begrænsningsovertrædelsen i denne OPDATERING aldrig ske under alle omstændigheder, da begrænsningen er opfyldt ved slutningen af OPDATERING. Tilstanden i slutningen af kommandoen er det, der betyder noget. De mellemliggende tilstande under udførelsen af en enkelt sætning bør ikke eksponeres for brugeren.
Det ser ud til, at PostgreSQL implementerer den ikke-udskydelige begrænsning ved at tjekke for dubletter efter hver række opdateret og fejler umiddelbart efter den første duplikat, hvilket i det væsentlige er fejlbehæftet. Men dette er et kendt problem, sandsynligvis lige så gammelt som PostgreSQL. I dag er løsningen for dette netop at bruge en UDSKYDLIG begrænsning. Og der er noget ironi i, at du ser på det som mangelfuldt, fordi det ikke lykkes, mens det på en eller anden måde formodes at være løsningen på fiaskoen i første omgang!
Sammendrag af status quo siden PostgreSQL 9.1
-
NOT DEFERRABLE
UNIQUE
ellerPRIMARY KEY
begrænsninger kontrolleres efter hver række . -
DEFERRABLE
begrænsninger sat tilIMMEDIATE
(INITIALLY IMMEDIATE
eller viaSET CONSTRAINTS
) er markeret efter hver erklæring . -
DEFERRABLE
begrænsninger sat tilDEFERRED
(INITIALLY DEFERRED
eller viaSET CONSTRAINTS
) kontrolleres efter hver transaktion .
Bemærk den særlige behandling af UNIQUE
/ PRIMARY KEY
constraints. Citerer manualsiden for CREATE TABLE
:
En begrænsning, der ikke kan udskydes, vil blive kontrolleret umiddelbart efter hver kommando .
Mens det står længere nede i Kompatibilitet sektion under Non-deferred uniqueness constraints
:
Når en UNIQUE
eller PRIMARY KEY
begrænsning kan ikke udskydes, PostgreSQL kontrollerer straks for unikhed hver gang en række indsættes eller ændres. SQL-standarden siger, at entydighed skal tvinges kun i slutningen af sætningen; dette gør en forskel, når f.eks. en enkelt kommando opdaterer flere nøgleværdier. For at opnå standardkompatibel adfærd skal du erklære begrænsningen somDEFERRABLE
men ikke udskudt (dvs. INITIALLY IMMEDIATE
). Vær opmærksom på, at dette kan være betydeligt langsommere end øjeblikkelig unikhedskontrol.
Fed fremhævelse mine.
Hvis du har brug for en FOREIGN KEY
begrænsninger for at referere til kolonne(r), DEFERRABLE
er ikke en mulighed, fordi (pr. dokumentation):
De refererede kolonner skal være kolonnerne i en ikke-udskydelig unik eller primær nøglebegrænsning i den refererede tabel.