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):
https://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 DEFERRABLEUNIQUEellerPRIMARY KEYbegrænsninger kontrolleres efter hver række . -
DEFERRABLEbegrænsninger sat tilIMMEDIATE(INITIALLY IMMEDIATEeller viaSET CONSTRAINTS) er markeret efter hver erklæring . -
DEFERRABLEbegrænsninger sat tilDEFERRED(INITIALLY DEFERREDeller 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.