PostgreSQL
 sql >> Teknologi Basis Data >  >> RDS >> PostgreSQL

Bagaimana cara menghapus baris duplikat dengan dependensi kunci asing?

Anda dapat melakukannya dengan lebih efisien dengan pernyataan SQL tunggal dengan CTE pengubah data .

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 di sini (hal 11)
SQL Fiddle (hal 9.6)

Ini seharusnya banyak lebih cepat dan lebih bersih. Perulangan relatif mahal, penanganan pengecualian relatif lebih mahal.
Yang lebih penting, referensi di lab diarahkan ke baris master masing-masing di cpt secara otomatis, yang belum ada dalam kode asli Anda. Jadi Anda dapat menghapus semua penipuan sekaligus .

Anda masih dapat membungkusnya dalam fungsi plpgsql atau SQL jika Anda mau.

Penjelasan

  1. Dalam plan CTE pertama , identifikasi baris master di setiap partisi dengan cdesc yang sama . Dalam kasus Anda, baris dengan recid minimum .

  2. Di upd_lab CTE ke-2 redirect semua baris yang mereferensikan penipuan ke baris master di cpt .

  3. Terakhir, hapus dupes, yang tidak akan memunculkan pengecualian karena baris yang bergantung ditautkan ke baris master yang tersisa secara virtual pada saat yang bersamaan.

ON DELETE RESTRICT

Semua CTE dan kueri utama dari pernyataan beroperasi pada snapshot yang sama dari tabel yang mendasarinya, hampir bersamaan . Mereka tidak melihat efek satu sama lain pada tabel yang mendasarinya:

Orang mungkin mengharapkan batasan FK dengan ON DELETE RESTRICT untuk mengajukan pengecualian karena, [per dokumentasi][3]:

Namun, pernyataan di atas adalah satu perintah dan, [manual lagi][3]:

Penekanan saya yang berani. Berfungsi untuk ON DELETE NO ACTION default yang tidak terlalu membatasi juga, tentu saja.

Namun berhati-hatilah terhadap transaksi bersamaan yang menulis ke tabel yang sama, tetapi itu adalah pertimbangan umum, tidak khusus untuk tugas ini.

Pengecualian berlaku untuk UNIQUE dan PRIMARY KEY kendala, tapi itu tidak menyangkut ini kasus:



  1. Database
  2.   
  3. Mysql
  4.   
  5. Oracle
  6.   
  7. Sqlserver
  8.   
  9. PostgreSQL
  10.   
  11. Access
  12.   
  13. SQLite
  14.   
  15. MariaDB
  1. Penyeimbangan Beban PostgreSQL Menggunakan HAProxy &Keepalive

  2. Apa gunanya ATURAN PostgreSQL?

  3. bilangan bulat di luar jangkauan dan ruang disk yang tersisa terlalu kecil untuk mengonversi id ke bigint dan solusi lainnya

  4. Perbarui nilai kolom PostgreSQL

  5. Adakah yang bisa menjelaskan bagaimana peran Postgresql, pengguna Postgresql, dan pengguna Linux saling berhubungan?