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

Jak usunąć zduplikowane wiersze z zależnościami kluczy obcych?

Możesz to zrobić znacznie wydajniej za pomocą pojedynczej instrukcji SQL z CTE modyfikacji danych .

WITH plan AS (
   SELECT *
   FROM  (
      SELECT recid, min(recid) OVER (PARTITION BY cdesc) AS master_recid
      FROM   cpt
      ) sub
   WHERE  recid <> master_recid  -- ... <> self
   )
 , upd_lab AS (
   UPDATE lab l
   SET    cpt_recid = p.master_recid   -- link to master recid ...
   FROM   plan p
   WHERE  l.cpt_recid = p.recid
   )
DELETE FROM cpt c
USING  plan p
WHERE  c.recid = p.recid
RETURNING c.recid;

db<>fiddle tutaj (str. 11)
Skrzypce SQL (str. 9.6)

Powinno to być dużo szybciej i czyściej. Zapętlanie jest stosunkowo drogie, obsługa wyjątków jest stosunkowo jeszcze droższa.
Co ważniejsze, referencje w lab są przekierowywane do odpowiedniego wiersza głównego w cpt automatycznie, czego jeszcze nie było w oryginalnym kodzie. Możesz więc usunąć wszystkie duplikaty naraz .

Jeśli chcesz, nadal możesz umieścić to w funkcji plpgsql lub SQL.

Wyjaśnienie

  1. W 1. CTE plan , zidentyfikuj wiersz główny w każdej partycji z tym samym cdesc . W Twoim przypadku wiersz z minimalnym recid .

  2. W drugim CTE upd_lab przekieruj wszystkie wiersze odwołujące się do duplikatu do wiersza głównego w cpt .

  3. Na koniec usuń duplikaty, co nie spowoduje wyjątków, ponieważ zależne wiersze są połączone z pozostałym wierszem głównym praktycznie w tym samym czasie.

ON DELETE RESTRICT

Wszystkie CTE i główne zapytanie wyciągu działają na tej samej migawce tabel bazowych, praktycznie równocześnie . Nie widzą efektów innych w tabelach poniżej:

Można by oczekiwać ograniczenia FK z ON DELETE RESTRICT zgłaszać wyjątki, ponieważ [w dokumentacji][3]:

Jednak powyższe stwierdzenie jest pojedynczym poleceniem i [instrukcja ponownie][3]:

Moje odważne podkreślenie. Działa dla mniej restrykcyjnego domyślnego ON DELETE NO ACTION oczywiście też.

Uważaj jednak na współbieżne transakcje zapisywania do tych samych tabel, ale jest to ogólna uwaga, a nie specyficzna dla tego zadania.

Wyjątek dotyczy UNIQUE i PRIMARY KEY ograniczenie, ale to nie dotyczy tego sprawa:



  1. Database
  2.   
  3. Mysql
  4.   
  5. Oracle
  6.   
  7. Sqlserver
  8.   
  9. PostgreSQL
  10.   
  11. Access
  12.   
  13. SQLite
  14.   
  15. MariaDB
  1. Zapomniałem hasła administratora w Postgres (instalacja Windows), nie można zresetować

  2. Zwróć wiele pól jako rekord w PostgreSQL z PL/pgSQL

  3. Błąd Postgres bytea podczas wiązania wartości null z przygotowanymi instrukcjami

  4. psql:FATAL:rola postgres nie istnieje

  5. Uzyskaj najczęstszą wartość dla każdej wartości innej kolumny w SQL