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

Postgresql elimina varias filas de varias tablas

Organizar las eliminaciones en cascada adecuadas es una buena idea y, por lo general, es la solución correcta para esto. Para ciertos casos especiales, hay otra solución que puede ser relevante.

Si necesita realizar varias eliminaciones en función de un conjunto común de datos, puede usar Expresiones de tabla comunes (CTE) .

Es difícil pensar en un ejemplo simple, ya que el caso de uso principal para esto puede cubrirse mediante eliminaciones en cascada.

Para el ejemplo, vamos a eliminar todos los elementos de la tabla A cuyo valor está en el conjunto de valores que estamos eliminando de la tabla B. Por lo general, estas serían claves, pero cuando no lo son, no se puede usar la eliminación en cascada. .

Para solucionar esto usas CTE

WITH Bdeletes AS (
    DELETE from B where IsSomethingToDelete = true returning ValueThatRelatesToA
)
delete from A where RelatedValue in (select ValueThatRelatesToA from Bdeletes)

Este ejemplo es deliberadamente simple porque mi punto no es discutir sobre el mapeo de teclas, etc., sino mostrar cómo se pueden realizar dos o más eliminaciones de un conjunto de datos compartido. Esto también puede ser mucho más complejo, incluidos los comandos de actualización, etc.

Aquí hay un ejemplo más complejo (de la base de datos personal de Darth Vader). En este caso, tenemos una tabla que hace referencia a una tabla de direcciones. Necesitamos borrar direcciones de la tabla de direcciones si están en su lista de planetas que ha destruido. Queremos usar esta información para eliminar de la tabla de personas, pero solo si estaban en el planeta (o en su lista de trofeos asesinados)

with AddressesToDelete as (
    select AddressId from Addresses a 
    join PlanetsDestroyed pd on pd.PlanetName = a.PlanetName
),
PeopleDeleted as (
    delete from People 
    where AddressId in (select * from AddressesToDelete)
    and OffPlanet = false 
    and TrophyKill = false
    returning Id
),
PeopleMissed as (
    update People 
    set AddressId=null, dead=(OffPlanet=false)
    where AddressId in (select * from AddressesToDelete)
    returning id
)
Delete from Addresses where AddressId in (select * from AddressesToDelete)

Ahora su base de datos está actualizada. No hay fallas de integridad debido a la eliminación de la dirección. Tenga en cuenta que si bien estamos devolviendo datos de la actualización y la primera eliminación, no significa que tengamos que usarlos. No estoy seguro de si puede poner una eliminación en un CTE sin datos devueltos (Mi SQL también puede estar equivocado en el uso de regresar de una actualización; no he podido probar esto porque Darth V. estaba en un mal humor.