PostgreSQL
 sql >> Base de données >  >> RDS >> PostgreSQL

Contrainte définie DIFFÉRABLE INITIALEMENT IMMÉDIAT est toujours DIFFÉRÉ ?

Je me souviens avoir soulevé un point presque identique lorsque PG9 était en état alpha. Voici la réponse de Tom Lane (développeur de base PG de haut niveau) :
http://archives.postgresql.org/pgsql-general/2010-01/msg00221.php

En bref :ne résoudra pas.

Cela ne veut pas dire que je suis d'accord avec votre suggestion selon laquelle le comportement actuel est un bogue. Regardez-le sous l'angle opposé :c'est le comportement de NOT DEFERRABLE c'est incorrect.

En fait, la violation de contrainte dans ce UPDATE ne devrait jamais se produire dans tous les cas, puisqu'à la fin du UPDATE la contrainte est satisfaite. L'état à la fin de la commande est ce qui compte. Les états intermédiaires lors de l'exécution d'une seule instruction ne doivent pas être exposés à l'utilisateur.

Il semble que PostgreSQL implémente la contrainte non différée en vérifiant les doublons après chaque mise à jour de ligne et en échouant immédiatement après le premier doublon, ce qui est essentiellement défectueux. Mais c'est un problème connu, probablement aussi vieux que PostgreSQL. De nos jours, la solution de contournement consiste précisément à utiliser une contrainte DEFERRABLE. Et il y a une certaine ironie dans le fait que vous le considérez comme déficient parce qu'il échoue, alors qu'il est censé être la solution à l'échec en premier lieu !

Résumé du statu quo depuis PostgreSQL 9.1

  • NOT DEFERRABLE UNIQUE ou PRIMARY KEY les contraintes sont vérifiées après chaque ligne .

  • DEFERRABLE contraintes définies sur IMMEDIATE (INITIALLY IMMEDIATE ou via SET CONSTRAINTS ) sont vérifiés après chaque instruction .

  • DEFERRABLE contraintes définies sur DEFERRED (INITIALLY DEFERRED ou via SET CONSTRAINTS ) sont vérifiés après chaque transaction .

Notez le traitement spécial de UNIQUE / PRIMARY KEY contraintes.Citer la page de manuel pour CREATE TABLE :

Une contrainte non reportable sera vérifiée immédiatement après chaque commande .

Bien qu'il soit indiqué plus bas dans la Compatibilité sous Non-deferred uniqueness constraints :

Lorsqu'un UNIQUE ou PRIMARY KEY la contrainte n'est pas reportable, PostgreSQL vérifie l'unicité immédiatement chaque fois qu'une ligne est insérée ou modifiée. La norme SQL indique que l'unicité doit être forcée uniquement à la fin de l'instruction; cela fait une différence lorsque, par exemple, une seule commande met à jour plusieurs valeurs de clé. Pour obtenir un comportement conforme à la norme, déclarez la contrainte comme DEFERRABLE mais non différé (c'est-à-dire INITIALLY IMMEDIATE ). Sachez que cela peut être beaucoup plus lent que la vérification immédiate de l'unicité.

J'insiste sur moi.

Si vous avez besoin d'une FOREIGN KEY contraintes pour référencer la ou les colonnes, DEFERRABLE n'est pas une option car (selon la documentation) :

Les colonnes référencées doivent être les colonnes d'une contrainte de clé unique ou primaire non différée dans la table référencée.