sql >> Database >  >> RDS >> PostgreSQL

Beperking gedefinieerd UITSTELBAAR EERST ONMIDDELLIJK is nog steeds UITGESTELD?

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 of PRIMARY KEY beperkingen worden gecontroleerd na elke rij .

  • DEFERRABLE beperkingen ingesteld op IMMEDIATE (INITIALLY IMMEDIATE of via SET CONSTRAINTS ) worden na elke stelling aangevinkt .

  • DEFERRABLE beperkingen ingesteld op DEFERRABLE (INITIALLY DEFERRED of via SET 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 of PRIMARY 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.



  1. Hoe GREATEST() werkt in MariaDB

  2. Beschermt mysql_real_escape_string() VOLLEDIG tegen SQL-injectie?

  3. Hoe twee kolommen in MySQL te vergelijken

  4. Kolomdefinitie ophalen voor resultaatset opgeslagen procedure