Banyak orang akan menyarankan Anda menggunakannya MERGE
, tetapi saya memperingatkan Anda untuk tidak menggunakannya. Secara default, itu tidak melindungi Anda dari kondisi konkurensi dan ras lebih dari beberapa pernyataan, dan itu memperkenalkan bahaya lain:
http://www.mssqltips.com/sqlservertip/3074/use-caution-with-sql-servers-merge-statement/
Bahkan dengan sintaks "sederhana" ini yang tersedia, saya masih lebih suka pendekatan ini (penanganan kesalahan dihilangkan untuk singkatnya):
SET TRANSACTION ISOLATION LEVEL SERIALIZABLE;
BEGIN TRANSACTION;
UPDATE dbo.table SET ... WHERE PK = @PK;
IF @@ROWCOUNT = 0
BEGIN
INSERT dbo.table(PK, ...) SELECT @PK, ...;
END
COMMIT TRANSACTION;
Banyak orang akan menyarankan cara ini:
SET TRANSACTION ISOLATION LEVEL SERIALIZABLE;
BEGIN TRANSACTION;
IF EXISTS (SELECT 1 FROM dbo.table WHERE PK = @PK)
BEGIN
UPDATE ...
END
ELSE
INSERT ...
END
COMMIT TRANSACTION;
Tetapi semua ini dicapai memastikan Anda mungkin perlu membaca tabel dua kali untuk menemukan baris yang akan diperbarui. Dalam sampel pertama, Anda hanya perlu menemukan baris sekali saja. (Dalam kedua kasus, jika tidak ada baris yang ditemukan dari pembacaan awal, terjadi penyisipan.)
Orang lain akan menyarankan cara ini:
BEGIN TRY
INSERT ...
END TRY
BEGIN CATCH
IF ERROR_NUMBER() = 2627
UPDATE ...
END CATCH
Namun, ini bermasalah jika tidak ada alasan lain selain membiarkan SQL Server menangkap pengecualian yang bisa Anda cegah sejak awal jauh lebih mahal, kecuali dalam skenario langka di mana hampir setiap insert gagal. Saya membuktikan banyak hal di sini: