Tôi tập hợp lại đoạn script sau để chứng minh thủ thuật này mà tôi đã sử dụng trong nhiều năm trước. Nếu bạn sử dụng nó, bạn sẽ cần phải sửa đổi nó cho phù hợp với mục đích của mình. Nhận xét theo sau:
/*
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
Mẹo ở đây là bạn có thể đặt giá trị trong các biến cục bộ trong câu lệnh Cập nhật. Ở trên, giá trị "cờ" chỉ được đặt nếu bản cập nhật hoạt động (nghĩa là, các tiêu chí cập nhật được đáp ứng); nếu không, nó sẽ không bị thay đổi (ở đây, bên trái là null), bạn có thể kiểm tra điều đó và xử lý cho phù hợp.
Đối với giao dịch và làm cho nó có thể tuần tự hóa, tôi muốn biết thêm về những gì phải được gói gọn trong giao dịch trước khi đề xuất cách tiếp tục.
- Addenda, theo dõi từ bình luận thứ hai bên dưới -----------
Ý tưởng của ông Saffron là một cách triệt để và chắc chắn để thực hiện quy trình này vì các khóa chính của bạn được xác định bên ngoài và được chuyển vào cơ sở dữ liệu (tức là bạn không sử dụng các cột nhận dạng - tôi thấy tốt, chúng thường bị sử dụng quá mức).
Tôi đã thực hiện thêm một số thử nghiệm (đã thêm ràng buộc khóa chính trên cột ContentId, bọc UPDATE và INSERT trong một giao dịch, thêm gợi ý có thể tuần tự hóa vào bản cập nhật) và vâng, điều đó sẽ làm được mọi thứ bạn muốn. Cập nhật không thành công sẽ khóa phạm vi trên phần đó của chỉ mục và điều đó sẽ chặn bất kỳ nỗ lực đồng thời nào để chèn giá trị mới đó vào cột. Tất nhiên, nếu N yêu cầu được gửi đồng thời, "đầu tiên" sẽ tạo ra hàng và nó sẽ được cập nhật ngay lập tức vào thứ hai, thứ ba, v.v. - trừ khi bạn đặt "khóa" ở đâu đó dọc theo dòng. Mẹo hay!
(Lưu ý rằng nếu không có chỉ mục trên cột khóa, bạn sẽ khóa toàn bộ bảng. Ngoài ra, khóa phạm vi có thể khóa các hàng ở "một trong hai bên" của giá trị mới - hoặc có thể chúng không, tôi đã không hãy kiểm tra cái đó. Không thành vấn đề, vì thời lượng của hoạt động phải [?] tính bằng mili giây một chữ số.)