PostgreSQL
 sql >> Datenbank >  >> RDS >> PostgreSQL

Constraint definiert DEFERRABLE ANFÄNGLICH SOFORT ist noch DEFERRED?

Ich erinnere mich, dass ich einen fast identischen Punkt angesprochen habe, als PG9 im Alpha-Status war. Hier war die Antwort von Tom Lane (bekannter PG-Core-Entwickler):
http://archives.postgresql.org/pgsql-general/2010-01/msg00221.php

Kurz gesagt:wird nicht behoben.

Um nicht zu sagen, dass ich Ihrem Vorschlag zustimme, dass das aktuelle Verhalten ein Fehler ist. Betrachten Sie es aus dem entgegengesetzten Blickwinkel:Es ist das Verhalten von NOT DEFERRABLE das ist falsch.

Tatsächlich sollte die Einschränkungsverletzung in diesem UPDATE auf keinen Fall auftreten, da am Ende des UPDATE die Einschränkung erfüllt ist. Entscheidend ist der Zustand am Ende des Befehls. Die Zwischenzustände während der Ausführung einer einzelnen Anweisung sollten dem Benutzer nicht offengelegt werden.

Es scheint, als würde PostgreSQL die nicht aufschiebbare Einschränkung implementieren, indem es nach jeder aktualisierten Zeile nach Duplikaten sucht und sofort beim ersten Duplikat fehlschlägt, was im Wesentlichen fehlerhaft ist. Dies ist jedoch ein bekanntes Problem, wahrscheinlich so alt wie PostgreSQL. Heutzutage besteht die Problemumgehung dafür genau darin, eine DEFERRABLE-Einschränkung zu verwenden. Und es liegt eine gewisse Ironie darin, dass Sie es als mangelhaft betrachten, weil es nicht scheitert, während es irgendwie von vornherein die Lösung für das Scheitern sein soll!

Zusammenfassung des Status quo seit PostgreSQL 9.1

  • NOT DEFERRABLE UNIQUE oder PRIMARY KEY Beschränkungen werden nach jeder Zeile geprüft .

  • DEFERRABLE Einschränkungen auf IMMEDIATE gesetzt (INITIALLY IMMEDIATE oder über SET CONSTRAINTS ) werden nach jeder Anweisung überprüft .

  • DEFERRABLE Einschränkungen auf DEFERRED gesetzt (INITIALLY DEFERRED oder über SET CONSTRAINTS ) werden nach jeder Transaktion geprüft .

Beachten Sie die Sonderbehandlung von UNIQUE / PRIMARY KEY Einschränkungen. Zitieren der Handbuchseite für CREATE TABLE :

Ein Constraint, der nicht aufschiebbar ist, wird sofort nach jedem Befehl geprüft .

Während es weiter unten in der Kompatibilität steht Abschnitt unter Non-deferred uniqueness constraints :

Wenn ein UNIQUE oder PRIMARY KEY Einschränkung ist nicht aufschiebbar, PostgreSQL prüft sofort auf Eindeutigkeit immer wenn eine Zeile eingefügt oder geändert wird. Der SQL-Standard besagt, dass Eindeutigkeit nur am Ende der Anweisung erzwungen werden sollte; Dies macht einen Unterschied, wenn beispielsweise ein einzelner Befehl mehrere Schlüsselwerte aktualisiert. Um standardkonformes Verhalten zu erhalten, deklarieren Sie die Einschränkung als DEFERRABLE aber nicht zurückgestellt (d. h. INITIALLY IMMEDIATE ). Beachten Sie, dass dies wesentlich langsamer sein kann als die sofortige Überprüfung der Eindeutigkeit.

Fettdruck von mir.

Wenn Sie einen FOREIGN KEY benötigen Beschränkungen zum Referenzieren der Spalte(n), DEFERRABLE ist keine Option, weil (laut Dokumentation):

Die referenzierten Spalten müssen die Spalten einer nicht aufschiebbaren Eindeutigkeits- oder Primärschlüsseleinschränkung in der referenzierten Tabelle sein.