Saya telah menulis proc yang disimpan yang akan melakukan pembaruan jika ada catatan, jika tidak maka akan melakukan penyisipan. Ini terlihat seperti ini:
update myTable set Col1=@col1, Col2=@col2 where ID=@ID
if @@rowcount = 0
insert into myTable (Col1, Col2) values (@col1, @col2)
Logika saya di balik menulisnya dengan cara ini adalah bahwa pembaruan akan melakukan pemilihan implisit menggunakan klausa where dan jika itu mengembalikan 0 maka penyisipan akan dilakukan.
Alternatif untuk melakukannya dengan cara ini adalah melakukan pemilihan dan kemudian berdasarkan jumlah baris yang dikembalikan, lakukan pembaruan atau penyisipan. Ini saya anggap tidak efisien karena jika Anda melakukan pembaruan itu akan menyebabkan 2 pilihan (panggilan pilih eksplisit pertama dan yang kedua implisit di mana pembaruan). Jika proc melakukan penyisipan maka tidak akan ada perbedaan dalam efisiensi.
Apakah logika saya terdengar di sini? Apakah ini cara Anda menggabungkan penyisipan dan pembaruan ke dalam proc yang disimpan?
Silakan baca postingan di blog saya untuk mengetahui pola yang baik dan aman yang dapat Anda gunakan. Ada banyak pertimbangan, dan jawaban yang diterima untuk pertanyaan ini jauh dari aman.
Untuk jawaban cepat, coba pola berikut. Ini akan bekerja dengan baik pada SQL 2000 dan yang lebih baru. SQL 2005 memberi Anda penanganan kesalahan yang membuka opsi lain dan SQL 2008 memberi Anda perintah MERGE.
sumber
Jika akan digunakan dengan SQL Server 2000/2005, kode asli harus disertakan dalam transaksi untuk memastikan bahwa data tetap konsisten dalam skenario bersamaan.
Ini akan menimbulkan biaya kinerja tambahan, tetapi akan memastikan integritas data.
Tambahkan, seperti yang telah disarankan, MERGE harus digunakan jika tersedia.
sumber
MERGE adalah salah satu fitur baru di SQL Server 2008.
sumber
Anda tidak hanya perlu menjalankannya dalam bertransaksi, tetapi juga membutuhkan tingkat isolasi yang tinggi. Sebenarnya tingkat isolasi default adalah Baca Berkomitmen dan kode ini perlu Serializable.
Mungkin menambahkan juga pemeriksaan kesalahan @@ dan rollback bisa menjadi ide yang bagus.
sumber
Jika Anda tidak melakukan penggabungan di SQL 2008, Anda harus mengubahnya menjadi:
jika @@ rowcount = 0 dan @@ error = 0
jika tidak, jika pembaruan gagal karena suatu alasan maka itu akan mencoba dan memasukkan setelah itu karena rowcount pada pernyataan gagal adalah 0
sumber
Penggemar berat UPSERT, benar-benar menghemat kode untuk dikelola. Berikut cara lain saya melakukannya: Salah satu parameter input adalah ID, jika ID adalah NULL atau 0, Anda tahu itu adalah INSERT, jika tidak maka update. Mengasumsikan aplikasi mengetahui jika ada ID, jadi tidak akan berfungsi dalam semua situasi, tetapi akan memotong setengah eksekusi jika Anda melakukannya.
sumber
Modifikasi pos Dima Malenko:
Anda dapat menjebak kesalahan dan mengirim rekaman ke tabel penyisipan yang gagal.
Saya perlu melakukan ini karena kami mengambil data apa pun yang dikirim melalui WSDL dan jika mungkin memperbaikinya secara internal.
sumber
Logika Anda tampaknya terdengar, tetapi Anda mungkin ingin mempertimbangkan untuk menambahkan beberapa kode untuk mencegah penyisipan jika Anda telah melewati kunci utama tertentu.
Sebaliknya, jika Anda selalu melakukan penyisipan jika pembaruan tidak memengaruhi rekaman apa pun, apa yang terjadi ketika seseorang menghapus rekaman sebelum Anda menjalankan "UPSERT"? Sekarang catatan yang Anda coba perbarui tidak ada, jadi itu akan membuat catatan sebagai gantinya. Itu mungkin bukan perilaku yang Anda cari.
sumber