Tengo una base de datos Postgresql en la que quiero hacer algunas eliminaciones en cascada. Sin embargo, las tablas no están configuradas con la regla ON DELETE CASCADE. ¿Hay alguna manera de que pueda eliminar y decirle a Postgresql que lo conecte en cascada solo por esta vez? Algo equivalente a
DELETE FROM some_table CASCADE;
Las respuestas a esta pregunta anterior hacen que parezca que no existe tal solución, pero pensé que haría esta pregunta explícitamente solo para estar seguro.
postgresql
Eli Courtwright
fuente
fuente
Respuestas:
No. Para hacerlo solo una vez, simplemente escribiría la declaración de eliminación para la tabla que desea en cascada.
fuente
Si realmente quiere lo
DELETE FROM some_table CASCADE;
que significa " eliminar todas las filas de la tablasome_table
", puede usar enTRUNCATE
lugar deDELETE
yCASCADE
siempre es compatible. Sin embargo, si desea utilizar la eliminación selectiva con unawhere
cláusula,TRUNCATE
no es suficiente.USO CON CUIDADO : esto eliminará todas las filas de todas las tablas que tienen una restricción de clave externa
some_table
y todas las tablas que tienen restricciones en esas tablas, etc.Postgres es compatible
CASCADE
con el comando TRUNCATE :Prácticamente esto es transaccional (es decir, puede revertirse), aunque no está completamente aislado de otras transacciones concurrentes y tiene varias otras advertencias. Lea los documentos para más detalles.
fuente
Escribí una función (recursiva) para eliminar cualquier fila en función de su clave principal. Escribí esto porque no quería crear mis restricciones como "en cascada de eliminación". Quería poder eliminar conjuntos complejos de datos (como un DBA) pero no permitir que mis programadores puedan eliminar en cascada sin pensar en todas las repercusiones. Todavía estoy probando esta función, por lo que puede haber errores, pero no lo intente si su base de datos tiene claves principales de varias columnas (y, por lo tanto, externas). Además, todas las claves deben poder representarse en forma de cadena, pero podrían escribirse de una manera que no tenga esa restricción. Utilizo esta función MUY ESPACIOSAMENTE de todos modos, valoro mis datos demasiado para permitir las restricciones en cascada en todo. Básicamente, esta función se pasa en el esquema, el nombre de la tabla y el valor primario (en forma de cadena), y comenzará por encontrar cualquier clave externa en esa tabla y se asegurará de que los datos no existan; si es así, se llama recursivamente a los datos encontrados. Utiliza una matriz de datos ya marcados para su eliminación para evitar bucles infinitos. Por favor, pruébelo y dígame cómo funciona para usted. Nota: es un poco lento. Yo lo llamo así:
select delete_cascade('public','my_table','1');
fuente
IN
operador con sub-selecciones en lugar de=
(por lo tanto, el paso para usar la lógica de conjuntos) sería mucho más rápido.Si lo entiendo correctamente, debería ser capaz de hacer lo que quiera al soltar la restricción de clave externa, agregar una nueva (que en cascada), hacer sus cosas y recrear la restricción de clave externa restrictiva.
Por ejemplo:
Por supuesto, debe resumir cosas como esas en un procedimiento, por el bien de su salud mental.
fuente
No puedo comentar la respuesta de Palehorse, así que agregué mi propia respuesta. La lógica de Palehorse está bien, pero la eficiencia puede ser mala con grandes conjuntos de datos.
Es más rápido si tiene índices en columnas y el conjunto de datos es mayor que unos pocos registros.
fuente
Sí, como han dicho otros, no hay un conveniente 'DELETE FROM my_table ... CASCADE' (o equivalente). Para eliminar registros secundarios protegidos por clave externa no en cascada y sus antepasados referenciados, sus opciones incluyen:
Supongo que es deliberado eludir las restricciones de clave externa; pero entiendo por qué en circunstancias particulares querrías hacerlo. Si es algo que hará con cierta frecuencia, y si está dispuesto a ignorar la sabiduría de los DBA en todas partes, es posible que desee automatizarlo con un procedimiento.
Vine aquí hace unos meses en busca de una respuesta a la pregunta "BORRADO EN CASCADA solo una vez" (¡originalmente hecha hace más de una década!). Obtuve algo de la solución inteligente de Joe Love (y la variante de Thomas CG de Vilhena), pero al final mi caso de uso tenía requisitos particulares (manejo de referencias circulares intra-tabla, por ejemplo) que me obligaron a adoptar un enfoque diferente. Ese enfoque finalmente se convirtió en recursive_delete (PG 10.10).
He estado usando recursively_delete en producción durante un tiempo, ahora, y finalmente me siento (cautelosamente) lo suficientemente seguro como para ponerlo a disposición de otros que podrían terminar buscando ideas. Al igual que con la solución de Joe Love, le permite eliminar gráficos completos de datos como si todas las restricciones de clave externa en su base de datos estuvieran configuradas momentáneamente en CASCADA, pero ofrece un par de características adicionales:
fuente
Puede utilizar para automatizar esto, puede definir la restricción de clave externa con
ON DELETE CASCADE
.Cito el manual de restricciones de clave externa :
fuente
Tomé la respuesta de Joe Love y la reescribí usando el
IN
operador con sub-selecciones en lugar de=
hacer la función más rápida (según la sugerencia de Hubbitus):fuente
in
operador y las subconsultas.La opción Eliminar con la cascada solo se aplica a las tablas con claves externas definidas. Si hace una eliminación, y dice que no puede porque violaría la restricción de clave externa, la cascada hará que elimine las filas ofensivas.
Si desea eliminar las filas asociadas de esta manera, primero deberá definir las claves externas. Además, recuerde que a menos que le indique explícitamente que comience una transacción, o que cambie los valores predeterminados, realizará una confirmación automática, lo que podría llevar mucho tiempo limpiar.
fuente