2012-07-06 39 views
5

Tôi đang sử dụng cột hàng tuần để xử lý đồng thời lạc quan và muốn lấy lại giá trị hàng tuần mới khi tôi đã thực hiện cập nhật sao cho lớp dữ liệu của tôi có giá trị mới nhất và có thể thực hiện một bản cập nhật khác với ngoại lệ đồng thời (trừ khi bản ghi đã được cập nhật bởi người khác).Nhận giá trị rowversion/timestamp mới nhất trong câu lệnh cập nhật - Sql Server

Tôi vừa mới tham gia vào lớp dữ liệu sau khi thực hiện cập nhật nhưng điều này không hiệu quả hoặc đáng tin cậy.

Đối với bảng sau:

CREATE TABLE PurchaseType 
(
    PurchaseTypeCode nvarchar(20) NOT NULL PRIMARY KEY CLUSTERED (PurchaseTypeCode), 
    Name nvarchar(50) NOT NULL, 
    TS rowversion NOT NULL 
) 

tôi đã cố gắng:

CREATE PROCEDURE PurchaseType_UpdateWithGet 
@PurchaseTypeCode nvarchar(20), 
@Name nvarchar(50), 
@TS rowversion OUTPUT  
AS 

UPDATE PurchaseType 
SET Name = @Name 
WHERE PurchaseTypeCode = @PurchaseTypeCode 
AND TS = @TS 

SELECT @TS = TS FROM PurchaseType WHERE PurchaseTypeCode = @PurchaseTypeCode 
GO 

nhưng không hoàn toàn hài lòng vì khả năng không nhận được giá trị rowverion từ bản cập nhật của ai đó. Sau đó, tôi đi qua báo cáo kết quả đầu ra trong tài liệu hướng dẫn rowversion (http://msdn.microsoft.com/en-us/library/ms182776.aspx/http://msdn.microsoft.com/en-us/library/ms177564.aspx) và cố gắng này:

CREATE PROCEDURE PurchaseType_UpdateWithOutput 
@PurchaseTypeCode nvarchar(20), 
@Name nvarchar(50), 
@TS rowversion OUTPUT  
AS 

DECLARE @Output TABLE (TS BINARY(8)) 

UPDATE PurchaseType 
SET Name = @Name 
    OUTPUT inserted.TS into @Output 
WHERE PurchaseTypeCode = @PurchaseTypeCode 
    AND TS = @TS 

SELECT TOP 1 @TS = TS FROM @Output 
GO 

này hoạt động tốt. Trong các thử nghiệm rất cơ bản của tôi (chỉ chạy 10000 cuộc gọi và định thời gian) tùy chọn OUTPUT mất khoảng 40% lâu hơn nhưng vẫn chưa đến một nửa mili giây. Không mất thời gian đo được với SET STATISTICS TIME ON.

Câu hỏi của tôi là, có ai biết cách nào tốt hơn/đơn giản hơn để thực hiện việc này không?

Tôi đã hy vọng cho một chức năng tôi có thể sử dụng tương tự như SCOPE_IDENTITY() cho cột nhận dạng nhưng không thể tìm thấy bất cứ điều gì như thế. Bất cứ ai biết nếu tôi đang thiếu một cái gì đó?

Xin cảm ơn trước.

+0

OUTPUT là con đường để đi để lấy bất kỳ giá trị tạo ra trên INSERT (và bao gồm SẮC nếu bạn hỏi tôi ...) –

+0

OK, cảm ơn vì điều đó. Bất kỳ lý do cụ thể nào khiến bạn ủng hộ OUTPUT trên SCOPE_IDENTITY? –

+2

Nó hoạt động với chèn nhiều hàng –

Trả lời

0

Từ MSDN:

@@ DBTS trả về giá trị timestamp cuối cùng được sử dụng cơ sở dữ liệu hiện hành. Giá trị dấu thời gian mới được tạo khi một hàng có cột dấu thời gian được chèn hoặc cập nhật.

+2

Cảm ơn, tôi không biết về điều đó. Trừ khi tôi nhầm. nó sẽ không hoạt động đáng tin cậy trong kịch bản này bởi vì nó là cơ sở dữ liệu rộng (tương tự như @@ ​​identity) chứ không phải là scoped đến thủ tục (tương tự như SCOPE_IDENTITY()). –

+0

Bạn đúng, đó là một nhược điểm. Tôi đoán OUTPUT là cách duy nhất còn lại để đi. –

0

Vấn đề của bạn là giữa cập nhật và chọn người khác cập nhật các hàng. Vì vậy, khi bạn chọn sau khi tuyên bố cập nhật của bạn, bạn không nhận được cùng một giá trị. Đây là vấn đề đọc không lặp lại được. Bạn nên sử dụng gợi ý khóa (UPDLOCK) với câu lệnh cập nhật. Khóa này sẽ cho phép người đọc (đó là khóa chia sẻ) nhưng sẽ chặn các nhà văn. Vì vậy, bạn sẽ nhận được các hàng tương tự sau khi cập nhật. Vì vậy, thủ tục lưu trữ của bạn nên được -

CREATE PROCEDURE PurchaseType_UpdateWithGet 
@PurchaseTypeCode nvarchar(20), 
@Name nvarchar(50), 
@TS rowversion OUTPUT  
AS 

UPDATE PurchaseType with (updlock) 
SET Name = @Name 
WHERE PurchaseTypeCode = @PurchaseTypeCode 
AND TS = @TS 

SELECT @TS = TS FROM PurchaseType WHERE PurchaseTypeCode = @PurchaseTypeCode 
GO 
Các vấn đề liên quan