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?