Entonces busca otras tablas en una CHECK
restricción .
CHECK
Se supone que las restricciones ejecutan IMMUTABLE
comprobaciones. Lo que pasa OK para una fila a la vez debe pasar OK en cualquier momento. Así es como CHECK
se definen las restricciones en el estándar SQL. Esa es también la razón de esta restricción ( según la documentación ):
Actualmente, las CHECK
expresiones no pueden contener subconsultas ni hacer referencia a variables que no sean columnas de la fila actual.
Ahora, las expresiones en CHECK
restricciones pueden usar funciones, incluso funciones definidas por el usuario. Esas deberían estar restringidas a IMMUTABLE
funciones, pero Postgres actualmente no aplica esto. De acuerdo con esta discusión relacionada sobre pgsql-hackers , una razón es permitir referencias a la hora actual, que no es IMMUTABLE
por naturaleza.
Pero está buscando filas de otra tabla, lo que viola por completo cómo CHECK
se supone que funcionan las restricciones. No me sorprende que pg_dump
no pueda prever esto.
Mueva su cheque en otra tabla a un disparador (que es la herramienta correcta), y debería funcionar con versiones modernas de Postgres.
PostgreSQL 9.2 o posterior
Si bien lo anterior es cierto para cualquier versión de Postgres, se han introducido varias herramientas con Postgres 9.2 para ayudar con su situación:
Opción pg_dump --exclude-table-data
Una solución simple sería volcar el db sin datos para la tabla infractora con:
--exclude-table-data=my_schema.my_tbl
Luego agregue solo los datos para esta tabla al final del volcado con:
--data-only --table=my_schema.my_tbl
Pero pueden surgir complicaciones con otras restricciones en la misma tabla. Hay una solución aún mejor :
NOT VALID
Existe el NOT VALID
modificador para las restricciones. Solo disponible para la restricción FK en v9.1, pero esto se extendió a las CHECK
restricciones en 9.2. Por documentación:
Si se marca NOT VALID
la restricción, se omite la verificación inicial potencialmente larga para verificar que todas las filas de la tabla cumplan la restricción. La restricción aún se aplicará contra inserciones o actualizaciones posteriores [...]
Un archivo de volcado simple de postgres consta de tres "secciones":
Postgres 9.2 también introdujo una opción para volcar secciones por separado -- section=sectionname
, pero eso no ayuda con el problema en cuestión.
Aquí es donde se pone interesante. Por documentación:
Los elementos posteriores a los datos incluyen definiciones de índices, disparadores, reglas y
restricciones distintas de las restricciones de verificación validadas . Los elementos previos a los datos incluyen todos los demás elementos de definición de datos.
El énfasis en negrita es mío.
Puede cambiar la CHECK
restricción ofensiva a NOT VALID
, que mueve la restricción a la post-data
sección. Suelta y recrea:
ALTER TABLE a DROP CONSTRAINT a_constr_1;
ALTER TABLE a ADD CONSTRAINT a_constr_1 CHECK (fail_if_b_empty()) NOT VALID;
Esto debería solucionar tu problema. Incluso puede dejar la restricción en ese estado , ya que eso refleja mejor lo que realmente hace: verificar nuevas filas, pero no ofrece garantías para los datos existentes. No hay nada malo con una NOT VALID
restricción de verificación. Si lo prefiere, puede validarlo más tarde:
ALTER TABLE a VALIDATE CONSTRAINT a_constr_1;
Pero luego vuelves al status quo ante.
-X
y-d
parapg_dump
.pg_dump
produce un volcado que se puede restaurar en una base de datos vacía.CHECK
restricción, todas las garantías se anulan, porque eso no se admite oficialmente, solo se tolera. Pero declarar laCHECK
restricción loNOT VALID
hizo funcionar para mí en todos los aspectos. Puede haber casos de esquina que nunca toqué ...