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
-
Dalam
planCTE pertama , identifikasi baris master di setiap partisi dengancdescyang sama . Dalam kasus Anda, baris denganrecidminimum . -
Di
upd_labCTE ke-2 redirect semua baris yang mereferensikan penipuan ke baris master dicpt. -
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: