sql >> Base de Datos >  >> RDS >> PostgreSQL

Restricción definida APLAZABLE INICIALMENTE INMEDIATO sigue siendo APLAZADA?

Recuerdo haber planteado un punto casi idéntico cuando PG9 estaba en estado alfa. Esta fue la respuesta de Tom Lane (desarrollador principal de PG de alto perfil):
http://archives.postgresql.org/pgsql-general/2010-01/msg00221.php

En resumen:no se arreglará.

No quiere decir que estoy de acuerdo con su sugerencia de que el comportamiento actual es un error. Míralo desde el ángulo opuesto:es el comportamiento de NOT DEFERRABLE eso es incorrecto.

De hecho, la violación de la restricción en esta ACTUALIZACIÓN nunca debería ocurrir en ningún caso, ya que al final de la ACTUALIZACIÓN se cumple la restricción. El estado al final del comando es lo que importa. Los estados intermedios durante la ejecución de una sola instrucción no deben exponerse al usuario.

Parece que PostgreSQL implementa la restricción no diferible al verificar si hay duplicados después de que cada fila se actualice y falla inmediatamente en el primer duplicado, que es esencialmente defectuoso. Pero este es un problema conocido, probablemente tan antiguo como PostgreSQL. Hoy en día, la solución para esto es precisamente usar una restricción DEFERRABLE. Y hay algo de ironía en que lo estás viendo como deficiente porque no falla, ¡mientras que de alguna manera se supone que es la solución a la falla en primer lugar!

Resumen del status quo desde PostgreSQL 9.1

  • NOT DEFERRABLE UNIQUE o PRIMARY KEY las restricciones se comprueban después de cada fila .

  • DEFERRABLE restricciones establecidas en IMMEDIATE (INITIALLY IMMEDIATE o a través de SET CONSTRAINTS ) se marcan después de cada declaración .

  • DEFERRABLE restricciones establecidas en DEFERRED (INITIALLY DEFERRED o a través de SET CONSTRAINTS ) se comprueban después de cada transacción .

Tenga en cuenta el tratamiento especial de UNIQUE / PRIMARY KEY restricciones. Citando la página del manual para CREATE TABLE :

Una restricción que no es diferible se verificará inmediatamente después de cada comando .

Si bien se establece más abajo en la Compatibilidad sección bajo Non-deferred uniqueness constraints :

Cuando un UNIQUE o PRIMARY KEY la restricción no es diferible, PostgreSQL comprueba la unicidad inmediatamente cada vez que se inserta o modifica una fila. El estándar SQL dice que la unicidad debe ser forzada solo al final de la declaración; esto marca la diferencia cuando, por ejemplo, un solo comando actualiza varios valores clave. Para obtener un comportamiento compatible con el estándar, declare la restricción como DEFERRABLE pero no diferido (es decir, INITIALLY IMMEDIATE ). Tenga en cuenta que esto puede ser significativamente más lento que la comprobación de unicidad inmediata.

Énfasis en negrita mío.

Si necesita alguna FOREIGN KEY restricciones para hacer referencia a la(s) columna(s), DEFERRABLE no es una opción porque (según la documentación):

Las columnas a las que se hace referencia deben ser las columnas de una restricción de clave primaria o única no diferible en la tabla a la que se hace referencia.