PostgreSQL
 sql >> Baza danych >  >> RDS >> PostgreSQL

Postgresql usuwa wiele wierszy z wielu tabel

Zorganizowanie prawidłowego usuwania kaskadowego jest mądre i zwykle jest właściwym rozwiązaniem tego problemu. W niektórych szczególnych przypadkach istnieje inne rozwiązanie, które może być istotne.

Jeśli potrzebujesz wykonać wiele operacji usuwania na podstawie wspólnego zestawu danych, możesz użyć Wspólne wyrażenia tabelowe (CTE) .

Trudno jest wymyślić prosty przykład, ponieważ główny przypadek użycia może być objęty kaskadowym usuwaniem.

Na przykład usuniemy wszystkie elementy w tabeli A, których wartość znajduje się w zbiorze wartości, które usuwamy z tabeli B. Zwykle będą to klucze, ale tam, gdzie ich nie ma, nie można użyć usuwania kaskadowego .

Aby rozwiązać ten problem, użyj CTE

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

Ten przykład jest celowo prosty, ponieważ moim celem nie jest kłótnia o mapowanie klawiszy itp., ale pokazanie, w jaki sposób można wykonać dwa lub więcej usunięcia ze współdzielonego zestawu danych. Może to być również znacznie bardziej złożone, w tym polecenia aktualizacji itp.

Oto bardziej złożony przykład (z osobistej bazy danych Dartha Vadera). W tym przypadku mamy tabelę, która odwołuje się do tabeli adresów. Musimy usunąć adresy z tabeli adresów, jeśli znajdują się na jego liście planet, które zniszczył. Chcemy użyć tych informacji do usunięcia z tabeli ludzi, ale tylko wtedy, gdy byli na planecie (lub na jego liście zabitych trofeów)

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)

Teraz jego baza danych jest aktualna. Brak błędów integralności spowodowanych usunięciem adresu. Pamiętaj, że podczas gdy zwracamy dane z aktualizacji i pierwszego usunięcia, nie oznacza to, że musimy z nich korzystać. Nie jestem pewien, czy można umieścić usunięcie w CTE bez zwracanych danych (Mój SQL może również mylić się w przypadku korzystania z powrotu z aktualizacji - nie byłem w stanie przetestować tego, ponieważ Darth V. był w zepsuty nastrój.



  1. Database
  2.   
  3. Mysql
  4.   
  5. Oracle
  6.   
  7. Sqlserver
  8.   
  9. PostgreSQL
  10.   
  11. Access
  12.   
  13. SQLite
  14.   
  15. MariaDB
  1. Jak odczytać usługę REST, która zwraca obiekt JSON i zapisać go w PostgreSQL za pomocą Mule ESB, Mule Studio

  2. Instrukcja EXECUTE...USING w PL/pgSQL nie działa z typem rekordu?

  3. Oracle do PostgreSQL — kursory i wspólne wyrażenia tabelowe

  4. Jak znaleźć posty oznaczone więcej niż jednym tagiem w Rails i Postgresql

  5. Skondensować lub zmienić numerację identyfikatorów dla wszystkich tabel i zresetować sekwencje do max(id)?