Bagaimana cara memasukkan atau memperbarui menggunakan permintaan tunggal?

26

Saya memiliki tes tabel yang memiliki kolom id yang kunci utama dan otomatis bertambah dan nama. Saya ingin menyisipkan catatan baru jika annd hanya jika tidak ada catatan. Misalnya

input adalah id = 30122 dan nama = john

jika ada catatan dengan id 30122 maka saya telah memperbarui kolom nama ke john, jika tidak ada catatan maka saya harus memasukkan catatan baru.

Saya bisa menggunakan 2 pertanyaan seperti

select * from test where id=30122

jika memiliki beberapa catatan maka saya bisa menggunakan update test set name='john' where id=3012

atau jika tidak memiliki catatan maka saya bisa menggunakan

insert into test(name) values('john')

Tapi saya ingin menggunakan permintaan tunggal?

Adakah yang tahu apakah itu mungkin?

SpringLearner
sumber
1
But I wanted to use single query?Mengapa?
Aaron Bertrand
@AaronBertrand belakang saya dikembangkan menggunakan java.So Jika saya menggunakan 2 quries maka saya harus memukul DB 2 times.So jika dapat dilakukan dengan menggunakan query tunggal maka mengapa untuk menggunakan 2 query
SpringLearner
1
Java tidak mendukung prosedur tersimpan, atau batch tunggal dengan dua pernyataan yang hanya membutuhkan satu klik ke database?
Aaron Bertrand
@ AaronBertrand dapatkah Anda memberikan contoh bagaimana Anda akan menangani ini dengan sql server 2008 atau lebih baru?
eaglei22
1
@ eaglei22 Saya akan menggunakan contoh ke-2 dalam jawaban vijayp di bawah ini. Saya masih tidak akan memilih MERGEdalam versi apa pun, bahkan SQL Server 2019. Beberapa latar belakang di sini .
Aaron Bertrand

Jawaban:

41

Anda bisa mencoba ini

IF EXISTS(select * from test where id=30122)
   update test set name='john' where id=3012
ELSE
   insert into test(name) values('john');

Pendekatan lain untuk kinerja yang lebih baik adalah

update test set name='john' where id=3012
IF @@ROWCOUNT=0
   insert into test(name) values('john');

dan juga membaca kebiasaan buruk ini untuk memulai awalan skema

vijayp
sumber
4
Contoh pertama adalah pemborosan dan sering dapat menyebabkan kebuntuan - saya tidak akan menyarankan itu sama sekali.
Aaron Bertrand
@ AaronBertrand peduli untuk menguraikan? Terima kasih
Hexo
5
@ Slap Tentu, dalam contoh pertama, Anda mengatakan: "Hei, SQL Server, apakah ada baris dengan ID ini?" SQL Server pergi mencari baris, mungkin menggunakan pemindaian, dan kemudian kembali dengan jawabannya. "Kenapa, ya, pengguna, aku punya baris dengan ID itu!" Lalu Anda berkata, "Oke, SQL Server, cari baris itu lagi , tapi kali ini, perbarui!" Apakah Anda melihat bagaimana melakukan pencarian atau memindai dua kali boros? Bisakah Anda bayangkan apa yang terjadi jika pengguna lain menanyakan SQL Server pertanyaan yang sama tentang keberadaan baris, sebelum Anda melanjutkan untuk melakukan sesuatu tentang hal itu?
Aaron Bertrand
Terima kasih, saya tidak mengerti mengapa yang pertama terancam macet sementara yang kedua tidak? Keduanya terdiri dari beberapa pernyataan yang dapat dicegat jika tidak dijalankan dengan kunci penuh. Apakah aku salah?
Hexo
2
@ 0x25b3 Bukannya yang satu terancam deadlock dan yang lain tidak, itu contoh pertama jauh lebih rentan terhadap mereka. Anda harus melakukan transaksi penuh dan benar dalam kedua kasus, tetapi orang tidak, jadi ...
Aaron Bertrand
17

Dengan asumsi SQL Server 2008 atau yang lebih baru, Anda dapat menggunakan MERGE:

Meja

CREATE TABLE dbo.Test
(
    id integer NOT NULL,
    name varchar(30) NULL,

    CONSTRAINT PK_dbo_Test__id
        PRIMARY KEY CLUSTERED (id)
);

Pertanyaan

MERGE dbo.Test WITH (SERIALIZABLE) AS T
USING (VALUES (3012, 'john')) AS U (id, name)
    ON U.id = T.id
WHEN MATCHED THEN 
    UPDATE SET T.name = U.name
WHEN NOT MATCHED THEN
    INSERT (id, name) 
    VALUES (U.id, U.name);

The SERIALIZABLEpetunjuk diperlukan untuk operasi yang benar di bawah concurrency tinggi .

Anda dapat menemukan perbandingan metode umum oleh Michael J. Swart di sini:

Mythbusting: Solusi Pembaruan / Sisipan Bersamaan

Evaldas Buinauskas
sumber
8
Gabung memiliki beberapa masalah .
vonPryz
link mitos yang ada di sana sangat bagus. Yang bagus!
JonnyRaa