Bạn có thể sử dụng KHÓA để làm cho mọi thứ CÓ THỂ XÁC ĐỊNH nhưng điều này làm giảm tính đồng thời. Tại sao không thử điều kiện chung trước ("chủ yếu là chèn hoặc chủ yếu là chọn"), sau đó là xử lý an toàn hành động "khắc phục hậu quả"? Đó là, mẫu "JFDI" ...
Chủ yếu là CHÈN dự kiến (công viên bóng 70-80% +):
Chỉ cần cố gắng chèn. Nếu nó không thành công, hàng đã được tạo. Không cần phải lo lắng về sự đồng thời vì TRY / CATCH giải quyết các bản sao cho bạn.
BEGIN TRY
INSERT Table VALUES (@Value)
SELECT @id = SCOPE_IDENTITY()
END TRY
BEGIN CATCH
IF ERROR_NUMBER() <> 2627
RAISERROR etc
ELSE -- only error was a dupe insert so must already have a row to select
SELECT @id = RowID FROM Table WHERE RowValue = @VALUE
END CATCH
Chủ yếu là CHỌN:
Tương tự, nhưng hãy cố gắng lấy dữ liệu trước. Không cần dữ liệu =INSERT. Một lần nữa, nếu 2 lệnh gọi đồng thời cố gắng CHÈN vì cả hai đều nhận thấy hàng thiếu các chốt điều khiển TRY / CATCH.
BEGIN TRY
SELECT @id = RowID FROM Table WHERE RowValue = @VALUE
IF @@ROWCOUNT = 0
BEGIN
INSERT Table VALUES (@Value)
SELECT @id = SCOPE_IDENTITY()
END
END TRY
BEGIN CATCH
IF ERROR_NUMBER() <> 2627
RAISERROR etc
ELSE
SELECT @id = RowID FROM Table WHERE RowValue = @VALUE
END CATCH
Cái thứ hai dường như lặp lại chính nó, nhưng nó rất đồng thời. Các khóa sẽ đạt được hiệu quả tương tự nhưng với chi phí đồng thời ...
Chỉnh sửa:
Tại sao không để sử dụng MERGE ...
Nếu bạn sử dụng mệnh đề OUTPUT, nó sẽ chỉ trả về những gì được cập nhật. Vì vậy, bạn cần một UPDATE giả để tạo bảng INSERTED cho mệnh đề OUTPUT. Nếu bạn phải cập nhật giả với nhiều lệnh gọi (như hàm ý của OP) thì rất nhiều nhật ký ghi chỉ để có thể sử dụng MERGE.