PostgreSQL
 sql >> Database >  >> RDS >> PostgreSQL

Postgresql elimina più righe da più tabelle

Organizzare le corrette eliminazioni a cascata è saggio e di solito è la soluzione corretta a questo. Per alcuni casi speciali, esiste un'altra soluzione che può essere rilevante.

Se è necessario eseguire più eliminazioni in base a un insieme comune di dati, è possibile utilizzare Espressioni di tabelle comuni (CTE) .

È difficile fornire un semplice esempio poiché il caso d'uso principale per questo può essere coperto da eliminazioni a cascata.

Per l'esempio elimineremo tutti gli elementi nella tabella A il cui valore è nell'insieme di valori che stiamo eliminando dalla tabella B. Di solito queste sarebbero chiavi, ma dove non lo sono, non è possibile utilizzare l'eliminazione a cascata .

Per risolvere questo problema usi i CTE

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

Questo esempio è volutamente semplice perché il mio punto non è discutere sulla mappatura dei tasti ecc., ma mostrare come è possibile eseguire due o più eliminazioni da un set di dati condiviso. Anche questo può essere molto più complesso, inclusi i comandi di aggiornamento ecc.

Ecco un esempio più complesso (dal database personale di Darth Vader). In questo caso, abbiamo una tabella che fa riferimento a una tabella di indirizzi. Dobbiamo eliminare gli indirizzi dalla tabella degli indirizzi se sono nella sua lista di pianeti che ha distrutto. Vogliamo utilizzare queste informazioni per eliminare dalla tabella delle persone, ma solo se erano sul pianeta (o nella sua lista delle uccisioni dei trofei)

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)

Ora il suo database è aggiornato. Nessun errore di integrità dovuto all'eliminazione dell'indirizzo. Tieni presente che mentre stiamo restituendo i dati dall'aggiornamento e dalla prima eliminazione, non significa che dobbiamo usarli. Non sono sicuro che tu possa inserire un'eliminazione in un CTE senza dati restituiti (il mio SQL potrebbe anche essere sbagliato sull'uso del ritorno da un aggiornamento - non sono stato in grado di testare l'esecuzione poiché Darth V. era in un umore irritabile.