Operasi UPSERT memperbarui atau menyisipkan baris dalam tabel, tergantung jika tabel sudah memiliki baris yang cocok dengan data:
if table t has a row exists that has key X:
update t set mystuff... where mykey=X
else
insert into t mystuff...
Karena Oracle tidak memiliki pernyataan UPSERT tertentu, apa cara terbaik untuk melakukan ini?
The pernyataan MERGE menggabungkan data antara dua tabel. Menggunakan DUAL memungkinkan kita untuk menggunakan perintah ini. Perhatikan bahwa ini tidak dilindungi terhadap akses bersamaan.
sumber
Contoh ganda di atas yang ada di PL / SQL sangat bagus karena saya ingin melakukan sesuatu yang serupa, tapi saya ingin sisi klien ... jadi di sini adalah SQL yang saya gunakan untuk mengirim pernyataan serupa langsung dari beberapa C #
Namun dari perspektif C # ini memberikan lebih lambat daripada melakukan pembaruan dan melihat apakah baris yang terpengaruh adalah 0 dan melakukan memasukkan jika itu.
sumber
MERGE
, dan saya lebih suka menggunakan lebih sederhanaDELETE
kemudianINSERT
.MERGE INTO mytable d USING (SELECT 1 id, 'x' name from dual) s ON (d.id = s.id) WHEN MATCHED THEN UPDATE SET d.name = s.name WHEN NOT MATCHED THEN INSERT (id, name) VALUES (s.id, s.name);
Alternatif lain tanpa mengecek pengecualian:
sumber
sumber
Tidak ada jawaban yang diberikan sejauh ini aman dalam menghadapi akses bersamaan , seperti yang ditunjukkan dalam komentar Tim Sylvester, dan akan menimbulkan pengecualian jika terjadi balapan. Untuk memperbaikinya, kombo sisipkan / perbarui harus dibungkus dengan semacam pernyataan loop, sehingga dalam kasus pengecualian semuanya dicoba lagi.
Sebagai contoh, inilah cara kode Grommit dapat dibungkus dalam satu lingkaran agar aman saat dijalankan secara bersamaan:
NB Dalam mode transaksi
SERIALIZABLE
, yang saya tidak rekomendasikan btw, Anda mungkin mengalami ORA-08177: sebaliknya, tidak dapat membuat serial akses untuk pengecualian transaksi ini .sumber
Saya ingin jawaban Grommit, kecuali itu membutuhkan nilai dupe. Saya menemukan solusi yang mungkin muncul sekali: http://forums.devshed.com/showpost.php?p=1182653&postcount=2
sumber
INSERT (B.CILT, B.SAYFA, B.KUTUK, B.MERNIS_NO) VALUES (E.CILT, E.SAYFA, E.KUTUK, E.MERNIS_NO);
?Catatan tentang dua solusi yang menyarankan:
1) Masukkan, jika pengecualian maka perbarui,
atau
2) Perbarui, jika sql% rowcount = 0 lalu masukkan
Pertanyaan apakah memasukkan atau memperbarui terlebih dahulu juga tergantung pada aplikasi. Apakah Anda mengharapkan lebih banyak sisipan atau lebih banyak pembaruan? Yang paling mungkin berhasil harus pergi dulu.
Jika Anda memilih yang salah, Anda akan mendapatkan banyak indeks yang tidak perlu dibaca. Bukan masalah besar tapi masih sesuatu yang perlu dipertimbangkan.
sumber
Saya telah menggunakan contoh kode pertama selama bertahun-tahun. Perhatikan notfound daripada count.
Kode di bawah ini adalah kode yang mungkin baru dan lebih baik
Pada contoh pertama pembaruan melakukan pencarian indeks. Itu harus, untuk memperbarui baris yang tepat. Oracle membuka kursor implisit, dan kami menggunakannya untuk membungkus sisipan yang sesuai sehingga kami tahu bahwa sisipan hanya akan terjadi ketika kunci tidak ada. Tetapi sisipan adalah perintah independen dan harus melakukan pencarian kedua. Saya tidak tahu cara kerja dari perintah penggabungan tetapi karena perintah adalah satu unit, Oracle bisa mengeksekusi memasukkan yang benar atau memperbarui dengan pencarian indeks tunggal.
Saya pikir penggabungan lebih baik ketika Anda memiliki beberapa pemrosesan yang harus dilakukan yang berarti mengambil data dari beberapa tabel dan memperbarui tabel, mungkin menyisipkan atau menghapus baris. Tetapi untuk kasus baris tunggal, Anda dapat mempertimbangkan kasus pertama karena sintaksis lebih umum.
sumber
Salin & tempel contoh untuk memasang satu tabel ke tabel lainnya, dengan MERGE:
Hasil:
sumber
Coba ini,
sumber
Dari http://www.praetoriate.com/oracle_tips_upserts.htm :
"Di Oracle9i, UPSERT dapat menyelesaikan tugas ini dalam satu pernyataan:"
sumber