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

Menggabungkan pernyataan INSERT dalam CTE yang memodifikasi data dengan ekspresi CASE

Anda tidak dapat membuat sarang INSERT pernyataan dalam CASE ekspresi. Berasal dari apa yang saya lihat, pendekatan yang sama sekali berbeda ini seharusnya berhasil:

Asumsi

  • Anda sebenarnya tidak memerlukan SELECT outer bagian luar .

  • dm_name / rm_name didefinisikan unik di dm / rm dan tidak kosong (<> '' ). Anda harus memiliki CHECK kendala untuk memastikan.

  • Kolom default untuk keduanya d_id dan r_id di z adalah NULL (default).

dm_name dan rm_name saling eksklusif

Jika keduanya tidak pernah hadir secara bersamaan.

WITH d1 AS (
   INSERT INTO d (dm_id)
   SELECT dm.dm_id 
   FROM   import
   JOIN   dm USING (dm_name)
   RETURNING d_id
   )
, r1 AS (
   INSERT INTO r (rm_id)
   SELECT rm.rm_id 
   FROM   import
   JOIN   rm USING (rm_name)
   RETURNING r_id
   )
, z1 AS (
   INSERT INTO z (d_id, r_id)
   SELECT d_id, r_id
   FROM d1 FULL JOIN r1 ON FALSE
   RETURNING z_id
   )
INSERT INTO port (z_id)
SELECT z_id
FROM   z1;

FULL JOIN .. ON FALSE menghasilkan tabel turunan dengan semua baris dari d1 dan r1 ditambahkan dengan NULL untuk masing-masing kolom lainnya (tidak ada tumpang tindih di antara keduanya). Jadi kita hanya perlu satu INSERT bukannya dua. Pengoptimalan kecil.

dm_name dan rm_name dapat hidup berdampingan

WITH i AS (
   SELECT dm.dm_id, rm.rm_id
   FROM   import
   LEFT   JOIN dm USING (dm_name)
   LEFT   JOIN rm USING (rm_name)
   )
, d1 AS (
   INSERT INTO d (dm_id)
   SELECT dm_id FROM i WHERE dm_id IS NOT NULL
   RETURNING dm_id, d_id
   )
, r1 AS (
   INSERT INTO r (rm_id)
   SELECT rm_id FROM i WHERE rm_id IS NOT NULL
   RETURNING rm_id, r_id
   )
, z1 AS (
   INSERT INTO z (d_id, r_id)
   SELECT d1.d_id, r1.r_id
   FROM   i
   LEFT   JOIN d1 USING (dm_id)
   LEFT   JOIN r1 USING (rm_id)
   WHERE  d1.dm_id IS NOT NULL OR
          r1.rm_id IS NOT NULL
   RETURNING z_id
   )
INSERT INTO port (z_id)
SELECT z_id FROM z1;

Catatan

Kedua versi juga berfungsi jika tidak ada.

INSERT tidak menyisipkan apa pun jika SELECT tidak mengembalikan baris.

Jika Anda harus berurusan dengan akses tulis bersamaan yang dapat bertentangan dengan operasi ini, perbaikan cepatnya adalah dengan mengunci tabel yang terlibat sebelum Anda menjalankan pernyataan ini dalam transaksi yang sama.




  1. Database
  2.   
  3. Mysql
  4.   
  5. Oracle
  6.   
  7. Sqlserver
  8.   
  9. PostgreSQL
  10.   
  11. Access
  12.   
  13. SQLite
  14.   
  15. MariaDB
  1. SQL pilih elemen di mana jumlah bidang kurang dari N

  2. PG::Kesalahan dalam klausa GROUP BY

  3. Impor dump MySQL ke database PostgreSQL

  4. Bagaimana cara menghapus carriage return dan baris baru di Postgresql?

  5. Cara Menyebarkan PostgreSQL untuk Ketersediaan Tinggi