Saya menyatukan skrip berikut untuk membuktikan trik yang saya gunakan di tahun-tahun sebelumnya. Jika Anda menggunakannya, Anda harus memodifikasinya agar sesuai dengan tujuan Anda. Komentar menyusul:
/*
CREATE TABLE Item
(
Title varchar(255) not null
,Teaser varchar(255) not null
,ContentId varchar(30) not null
,RowLocked bit not null
)
UPDATE item
set RowLocked = 1
where ContentId = 'Test01'
*/
DECLARE
@Check varchar(30)
,@pContentID varchar(30)
,@pTitle varchar(255)
,@pTeaser varchar(255)
set @pContentID = 'Test01'
set @pTitle = 'TestingTitle'
set @pTeaser = 'TestingTeasier'
set @check = null
UPDATE dbo.Item
set
@Check = ContentId
,Title = @pTitle
,Teaser = @pTeaser
where ContentID = @pContentID
and RowLocked = 0
print isnull(@check, '<check is null>')
IF @Check is null
INSERT dbo.Item (ContentID, Title, Teaser, RowLocked)
values (@pContentID, @pTitle, @pTeaser, 0)
select * from Item
Triknya di sini adalah Anda dapat menetapkan nilai dalam variabel lokal dalam pernyataan Update. Di atas, nilai "bendera" akan disetel hanya jika pembaruan berfungsi (yaitu, kriteria pembaruan terpenuhi); jika tidak, itu tidak akan berubah (di sini, dibiarkan nol), Anda dapat memeriksanya, dan memprosesnya.
Untuk transaksi dan membuatnya serial, saya ingin tahu lebih banyak tentang apa yang harus dienkapsulasi dalam transaksi sebelum menyarankan bagaimana untuk melanjutkan.
-- Tambahan, tindak lanjut dari komentar kedua di bawah ------------
Ide Mr. Saffron adalah cara yang menyeluruh dan solid untuk menerapkan rutinitas ini karena kunci utama Anda ditentukan di luar dan diteruskan ke database (yaitu Anda tidak menggunakan kolom identitas--baiklah menurut saya, mereka sering digunakan secara berlebihan).
Saya melakukan beberapa pengujian lagi (menambahkan batasan kunci utama pada kolom ContentId, membungkus UPDATE dan INSERT dalam sebuah transaksi, menambahkan petunjuk serializable ke pembaruan) dan ya, itu akan melakukan semua yang Anda inginkan. Pembaruan yang gagal menampar kunci rentang pada bagian indeks itu, dan itu akan memblokir setiap upaya simultan untuk memasukkan nilai baru itu di kolom. Tentu saja, jika N permintaan diajukan secara bersamaan, "pertama" akan membuat baris, dan akan segera diperbarui oleh yang kedua, ketiga, dst.--kecuali jika Anda menyetel "kunci" di suatu tempat di sepanjang baris. Trik yang bagus!
(Perhatikan bahwa tanpa indeks pada kolom kunci, Anda akan mengunci seluruh tabel. Juga, kunci rentang dapat mengunci baris di "kedua sisi" dari nilai baru--atau mungkin tidak, saya tidak uji yang itu. Seharusnya tidak masalah, karena durasi operasi harus [?] dalam milidetik satu digit.)