Bạn cần phải làm điều này trong giao dịch để đảm bảo hai khách hàng đồng thời sẽ không chèn cùng fieldValue hai lần:
SET TRANSACTION ISOLATION LEVEL SERIALIZABLE
BEGIN TRANSACTION
DECLARE @id AS INT
SELECT @id = tableId FROM table WHERE [email protected]
IF @id IS NULL
BEGIN
INSERT INTO table (fieldValue) VALUES (@newValue)
SELECT @id = SCOPE_IDENTITY()
END
SELECT @id
COMMIT TRANSACTION
bạn cũng có thể sử dụng để giảm Double-checked locking khóa overhead
DECLARE @id AS INT
SELECT @id = tableID FROM table (NOLOCK) WHERE [email protected]
IF @id IS NULL
BEGIN
SET TRANSACTION ISOLATION LEVEL SERIALIZABLE
BEGIN TRANSACTION
SELECT @id = tableID FROM table WHERE [email protected]
IF @id IS NULL
BEGIN
INSERT INTO table (fieldValue) VALUES (@newValue)
SELECT @id = SCOPE_IDENTITY()
END
COMMIT TRANSACTION
END
SELECT @id
đối với lý do tại sao cô lập CẤP sERIALIZABLE là cần thiết, khi bạn đang ở trong một giao dịch serializable, tha SELECT đầu tiên t truy cập vào bảng tạo ra một phạm vi khóa bao gồm nơi mà các hồ sơ nên được, vì vậy không ai khác có thể chèn cùng một kỷ lục cho đến khi giao dịch này kết thúc.
Nếu không có mức độ cô lập, mức cô lập mặc định (READ COMMITTED) sẽ không khóa bảng tại thời điểm đọc, vì vậy giữa SELECT và UPDATE, ai đó vẫn có thể chèn. Các giao dịch với mức độ cô lập READ COMMITTED không làm cho SELECT khóa. Giao dịch với READEATABLE READS khóa bản ghi (nếu tìm thấy) nhưng không phải là khoảng trống.
Bạn đang sử dụng ngôn ngữ lập trình nào? Điều này có thể được thực hiện tốt hơn ở bên trong một giao dịch. –
bản sao có thể có của [Chỉ chèn hàng nếu nó chưa có ở đó] (http://stackoverflow.com/questions/3407857/only-inserting-a-row-if-its-not-already-there) –
Đây là câu hỏi cũ; câu hỏi 'Chỉ chèn một hàng' phải được đóng dưới dạng bản sao của câu hỏi này, chứ không phải theo cách khác. –