sql >> Databasteknik >  >> RDS >> PostgreSQL

Begränsning definierad UPPHÖJBAR INitialt OMEDELBART är fortfarande UPPHÖJD?

Jag minns att jag tog upp en nästan identisk punkt när PG9 var i alfatillstånd. Här var svaret från Tom Lane (högprofils PG kärnutvecklare):
http://archives.postgresql.org/pgsql-general/2010-01/msg00221.php

Kort sagt:kommer inte att fixa.

För att inte säga att jag håller med ditt förslag att det nuvarande beteendet är en bugg. Titta på det från motsatt vinkel:det är beteendet hos NOT DEFERRABLE det är felaktigt.

Faktum är att begränsningsöverträdelsen i denna UPPDATERING aldrig ska ske i något fall, eftersom begränsningen är uppfylld i slutet av UPPDATERING. Tillståndet i slutet av kommandot är det som är viktigt. Mellantillstånden under exekveringen av en enskild sats bör inte exponeras för användaren.

Det verkar som att PostgreSQL implementerar den icke uppskjutbara begränsningen genom att kontrollera efter dubbletter efter varje rad uppdaterad och misslyckas omedelbart efter den första dubbletten, vilket i huvudsak är felaktigt. Men det här är ett känt problem, förmodligen lika gammalt som PostgreSQL. Nuförtiden är lösningen för detta just att använda en DEFERRABLE-begränsning. Och det finns en viss ironi i att du ser på det som bristfälligt eftersom det inte misslyckas, medan det på något sätt är tänkt att vara lösningen på misslyckandet i första hand!

Sammanfattning av status quo sedan PostgreSQL 9.1

  • NOT DEFERRABLE UNIQUE eller PRIMARY KEY begränsningar kontrolleras efter varje rad .

  • DEFERRABLE begränsningar inställda på IMMEDIATE (INITIALLY IMMEDIATE eller via SET CONSTRAINTS ) kontrolleras efter varje påstående .

  • DEFERRABLE begränsningar satt till DEFERRED (INITIALLY DEFERRED eller via SET CONSTRAINTS ) kontrolleras efter varje transaktion .

Observera specialbehandlingen av UNIQUE / PRIMARY KEY constraints. Citerar manualsidan för CREATE TABLE :

En begränsning som inte kan skjutas upp kommer att kontrolleras omedelbart efter varje kommando .

Medan det står längre ner i Kompatibilitet avsnittet under Non-deferred uniqueness constraints :

När en UNIQUE eller PRIMARY KEY begränsning kan inte skjutas upp, PostgreSQL kontrollerar omedelbart efter unikhet närhelst en rad infogas eller ändras. SQL-standarden säger att unikhet ska framtvingas endast i slutet av satsen; detta gör skillnad när, till exempel, ett enda kommando uppdaterar flera nyckelvärden. För att erhålla standardkompatibelt beteende, deklarera begränsningen somDEFERRABLE men inte uppskjuten (dvs. INITIALLY IMMEDIATE ). Var medveten om att detta kan vara betydligt långsammare än omedelbar unikhetskontroll.

Djärv betoning min.

Om du behöver någon FOREIGN KEY begränsningar för att referera till kolumn(erna), DEFERRABLE är inte ett alternativ eftersom (per dokumentation):

De refererade kolumnerna måste vara kolumnerna för en icke-uppskjutbar unik eller primär nyckelrestriktion i den refererade tabellen.



  1. Vilka är olika typer av begränsningar tillgängliga i SQL Server - SQL Server / T-SQL självstudie del 50

  2. Hur kan jag importera en .sql-fil till min Heroku postgres-databas?

  3. Konvertera månadsnummer till månadsnamnsfunktion i SQL

  4. Översikt över kommandot DBCC SHRINKFILE