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

Apa yang terjadi dengan duplikat saat menyisipkan banyak baris?

INSERT hanya akan menyisipkan semua baris dan tidak ada spesial akan terjadi, kecuali Anda memiliki semacam batasan melarang nilai duplikat / tumpang tindih (PRIMARY KEY , UNIQUE , CHECK atau EXCLUDE kendala) - yang tidak Anda sebutkan dalam pertanyaan Anda. Tapi itulah yang mungkin Anda khawatirkan.

Dengan asumsi UNIQUE atau batasan PK pada (col1,col2) , Anda berurusan dengan buku teks UPSERT situasi. Banyak pertanyaan dan jawaban terkait dapat ditemukan di sini.

Umumnya, jika ada batasan dilanggar, pengecualian muncul yang (kecuali terjebak dalam subtransaksi seperti yang mungkin dalam bahasa sisi server prosedural seperti plpgsql) akan memutar kembali tidak hanya pernyataan, tetapi seluruh transaksi .

Tanpa penulisan bersamaan

Yaitu:Tidak ada transaksi lain yang akan mencoba menulis ke tabel yang sama secara bersamaan.

  • Kecualikan baris yang sudah ada di tabel dengan WHERE NOT EXISTS ... atau teknik lain yang berlaku:

  • Pilih baris yang tidak ada di tabel lain

  • Dan jangan lupa untuk menghapus duplikat di dalam set yang dimasukkan juga, yang tidak dikecualikan oleh semi-anti-join WHERE NOT EXISTS ...

Salah satu teknik untuk menangani keduanya sekaligus adalah EXCEPT :

INSERT INTO tbl (col1, col2)
VALUES
  (text 'v1', text 'v2')  -- explicit type cast may be needed in 1st row
, ('v3', 'v4')
, ('v3', 'v4')  -- beware of dupes in source
EXCEPT SELECT col1, col2 FROM tbl;

EXCEPT tanpa kata kunci ALL melipat baris duplikat di sumber. Jika Anda tahu tidak ada penipuan, atau Anda tidak ingin melipat duplikat secara diam-diam, gunakan EXCEPT ALL (atau salah satu teknik lainnya). Lihat:

  • Menggunakan klausa KECUALI di PostgreSQL

Umumnya, jika tabel target besar , WHERE NOT EXISTS dalam kombinasi dengan DISTINCT pada sumbernya mungkin akan lebih cepat:

INSERT INTO tbl (col1, col2)
SELECT *
FROM  (
   SELECT DISTINCT *
   FROM  (
       VALUES
         (text 'v1', text'v2')
       , ('v3', 'v4')
       , ('v3', 'v4')  -- dupes in source
      ) t(c1, c2)
   ) t
WHERE NOT EXISTS (
   SELECT FROM tbl
   WHERE  col1 = t.c1 AND col2 = t.c2
   );

Jika ada banyak penipuan, ada baiknya melipatnya di sumbernya terlebih dahulu. Jika tidak, gunakan satu subkueri lebih sedikit.

Terkait:

  • Pilih baris yang tidak ada di tabel lain

Dengan penulisan bersamaan

Gunakan Postgres UPSERT implementasi INSERT ... ON CONFLICT ... di Postgres 9.5 atau lebih baru:

INSERT INTO tbl (col1,col2)
SELECT DISTINCT *  -- still can't insert the same row more than once
FROM  (
   VALUES
     (text 'v1', text 'v2')
   , ('v3','v4')
   , ('v3','v4')  -- you still need to fold dupes in source!
  ) t(c1, c2)
ON CONFLICT DO NOTHING;  -- ignores rows with *any* conflict!

Bacaan lebih lanjut:

  • Bagaimana cara menggunakan RETURNING dengan ON CONFLICT di PostgreSQL?
  • Bagaimana cara menyisipkan baris yang berisi kunci asing?

Dokumentasi:

  • Panduan
  • Halaman komit
  • Halaman Wiki Postgres

Jawaban referensi Craig untuk UPSERT masalah:

  • Bagaimana cara UPSERT (MERGE, INSERT ... ON DUPLICATE UPDATE) di PostgreSQL?


  1. Database
  2.   
  3. Mysql
  4.   
  5. Oracle
  6.   
  7. Sqlserver
  8.   
  9. PostgreSQL
  10.   
  11. Access
  12.   
  13. SQLite
  14.   
  15. MariaDB
  1. Permintaan untuk ORDER BY jumlah baris yang dikembalikan dari SELECT lain

  2. Status Manajemen Cadangan Sumber Terbuka Saat Ini untuk PostgreSQL

  3. kueri sql dinamis di postgres

  4. Bagaimana cara saya terhubung ke PostgreSQL tanpa menentukan nama database?

  5. Oracle ke PostgreSQL:sintaks gabungan luar ANSI di PostgreSQL