sql >> Database >  >> RDS >> PostgreSQL

Postgresql verwijdert meerdere rijen uit meerdere tabellen

Het regelen van de juiste trapsgewijze verwijderingen is verstandig en is meestal de juiste oplossing hiervoor. Voor bepaalde speciale gevallen is er een andere oplossing die relevant kan zijn.

Als u meerdere verwijderingen moet uitvoeren op basis van een gemeenschappelijke set gegevens, kunt u gebruiken Algemene tabeluitdrukkingen (CTE) .

Het is moeilijk om een ​​eenvoudig voorbeeld te bedenken, omdat de belangrijkste use-case hiervoor kan worden afgedekt door trapsgewijze verwijderingen.

Voor het voorbeeld gaan we alle items in tabel A verwijderen waarvan de waarde in de set met waarden zit die we uit tabel B verwijderen. Meestal zijn dit sleutels, maar als dat niet het geval is, kan trapsgewijze verwijderen niet worden gebruikt .

Om dit op te lossen gebruik je CTE's

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

Dit voorbeeld is met opzet eenvoudig omdat het niet mijn bedoeling is om ruzie te maken over key mapping enz., maar om te laten zien hoe twee of meer verwijderingen kunnen worden uitgevoerd op een gedeelde dataset. Dit kan ook veel complexer zijn, inclusief update-commando's enz.

Hier is een complexer voorbeeld (uit de persoonlijke database van Darth Vader). In dit geval hebben we een tabel die verwijst naar een adrestabel. We moeten adressen uit de adrestabel verwijderen als ze in zijn lijst van planeten staan ​​die hij heeft vernietigd. We willen deze informatie gebruiken om te verwijderen uit de tabel met mensen, maar alleen als ze op de planeet waren (of op zijn trophy-kill-lijst)

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 is zijn database up-to-date. Geen integriteitsfouten als gevolg van adresverwijdering. Houd er rekening mee dat hoewel we gegevens van de update en de eerste verwijdering retourneren, dit niet betekent dat we deze moeten gebruiken. Ik weet niet zeker of u een verwijdering in een CTE zonder geretourneerde gegevens kunt plaatsen (Mijn SQL kan ook verkeerd zijn over het gebruik van terugkeer van een update - ik heb dit niet kunnen testen omdat Darth V. in een chagrijnig humeur.



  1. MySQL met JOIN gebruikt geen index

  2. Realtime scoren

  3. PHP naar MySQL SSL-verbindingen

  4. Oracle RAC op clouds van derden