sql >> Databasteknik >  >> RDS >> PostgreSQL

Postgresql ta bort flera rader från flera tabeller

Att ordna ordentliga överlappande borttagningar är klokt och är vanligtvis den rätta lösningen på detta. För vissa specialfall finns det en annan lösning på detta som kan vara relevant.

Om du behöver utföra flera raderingar baserat på en gemensam uppsättning data kan du använda Vanliga tabelluttryck (CTE) .

Det är svårt att komma på ett enkelt exempel eftersom det huvudsakliga användningsfallet för detta kan täckas av kaskadraderingar.

För exemplet kommer vi att ta bort alla objekt i tabell A vars värde finns i den uppsättning värden vi tar bort från tabell B. Vanligtvis skulle dessa vara nycklar, men där de inte är det, kan överlappande radering inte användas .

För att lösa detta använder du CTEs

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

Det här exemplet är medvetet enkelt eftersom min poäng inte är att argumentera om nyckelmappning etc, utan att visa hur två eller flera raderingar kan utföras från en delad datauppsättning. Detta kan också vara mycket mer komplext, inklusive uppdateringskommandon etc.

Här är ett mer komplext exempel (från Darth Vaders personliga databas). I det här fallet har vi en tabell som refererar till en adresstabell. Vi måste ta bort adresser från adresstabellen om de finns i hans lista över planeter han har förstört. Vi vill använda denna information för att radera från folktabellen, men bara om de var på planeten (eller på hans trophy-kill-lista)

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)

Nu är hans databas uppdaterad. Inga integritetsfel på grund av radering av adress. Observera att medan vi returnerar data från uppdateringen och den första raderingen, betyder det inte att vi måste använda den. Jag är osäker på om du kan lägga en radering i en CTE utan returnerad data (Min SQL kan också ha fel på användningen av att returnera från en uppdatering - jag har inte kunnat testköra detta eftersom Darth V. var i en knasig stämning.



  1. MySQL - hur man front pad postnummer med 0?

  2. Använder Dapper QueryMultiple i Oracle

  3. SQL - Operand-datatypen datetime2 är ogiltig för subtractoperator

  4. Saknade sekvenser i HSQL för testning