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

Postgresql slette flere rækker fra flere tabeller

Det er klogt at arrangere korrekt overlappende sletninger og er normalt den rigtige løsning på dette. I visse specielle tilfælde er der en anden løsning på dette, som kan være relevant.

Hvis du har brug for at udføre flere sletninger baseret på et fælles sæt data, kan du bruge Almindelige tabeludtryk (CTE) .

Det er svært at komme med et simpelt eksempel, da den primære brugssituation for dette kan dækkes af kaskadende sletninger.

I eksemplet vil vi slette alle elementer i tabel A, hvis værdi er i det sæt af værdier, vi sletter fra tabel B. Normalt vil disse være nøgler, men hvor de ikke er det, kan kaskadende sletning ikke bruges .

For at løse dette bruger du CTE'er

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

Dette eksempel er bevidst simpelt, fordi min pointe ikke er at skændes om nøglekortlægning osv., men at vise hvordan to eller flere sletninger kan udføres fra et delt datasæt. Dette kan også være meget mere komplekst, herunder opdateringskommandoer osv.

Her er et mere komplekst eksempel (fra Darth Vaders personlige database). I dette tilfælde har vi en tabel, der refererer til en adressetabel. Vi er nødt til at slette adresser fra adressetabellen, hvis de er på hans liste over planeter, han har ødelagt. Vi ønsker at bruge disse oplysninger til at slette fra personer-tabellen, men kun hvis de var på planeten (eller på hans trofæ-dræbningsliste)

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 er hans database opdateret. Ingen integritetsfejl på grund af adressesletning. Bemærk, at mens vi returnerer data fra opdateringen og den første sletning, betyder det ikke, at vi skal bruge dem. Jeg er usikker på, om du kan lægge en sletning i en CTE uden returnerede data (Min SQL kan også være forkert på brugen af ​​at returnere fra en opdatering - jeg har ikke været i stand til at teste køre dette, da Darth V. var i en sur stemning.



  1. PHP Advarsel:mysql_query() forventer, at parameter 1 er streng

  2. Mærkelig opførsel i Postgresql

  3. indeks på url eller hashing i betragtning af RAM

  4. Brug af en primær nøgle med et WithoutRowID