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

Postgresql supprime plusieurs lignes de plusieurs tables

Il est judicieux d'organiser des suppressions en cascade appropriées et c'est généralement la bonne solution. Pour certains cas particuliers, il existe une autre solution qui peut être pertinente.

Si vous devez effectuer plusieurs suppressions basées sur un ensemble commun de données, vous pouvez utiliser Expressions de table communes (CTE) .

Il est difficile de trouver un exemple simple car le cas d'utilisation principal peut être couvert par des suppressions en cascade.

Pour l'exemple, nous allons supprimer tous les éléments de la table A dont la valeur se trouve dans l'ensemble de valeurs que nous supprimons de la table B. Habituellement, ce sont des clés, mais là où elles ne le sont pas, la suppression en cascade ne peut pas être utilisée. .

Pour résoudre ce problème, vous utilisez des CTE

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

Cet exemple est délibérément simple car mon but n'est pas de discuter du mappage de clés, etc., mais de montrer comment deux ou plusieurs suppressions peuvent être effectuées sur un ensemble de données partagé. Cela peut aussi être beaucoup plus complexe, y compris les commandes de mise à jour, etc.

Voici un exemple plus complexe (issu de la base de données personnelle de Dark Vador). Dans ce cas, nous avons une table qui fait référence à une table d'adresses. Nous devons supprimer les adresses de la table d'adresses si elles figurent dans sa liste de planètes qu'il a détruites. Nous voulons utiliser ces informations pour supprimer de la table des personnes, mais seulement s'ils étaient sur la planète (ou sur sa liste de trophées tués)

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)

Maintenant, sa base de données est à jour. Aucun échec d'intégrité dû à la suppression de l'adresse. Notez que même si nous renvoyons les données de la mise à jour et de la première suppression, cela ne signifie pas que nous devons les utiliser. Je ne sais pas si vous pouvez mettre une suppression dans un CTE sans données renvoyées (mon SQL peut également être erroné sur l'utilisation du retour d'une mise à jour - je n'ai pas pu tester cela car Dark V. était dans un humeur grincheuse.