2012-07-06 4 views
5

मैं आशावादी समेकन को संभालने के लिए पंक्तिवर्धक कॉलम का उपयोग कर रहा हूं और जब मैंने अद्यतन किया है तो नई पंक्तिवर्तन मान वापस प्राप्त करना चाहते हैं ताकि मेरी डेटा परत का नवीनतम मूल्य हो और एक समवर्ती अपवाद प्राप्त करने के साथ एक और अद्यतन कर सकते हैं (जब तक कि रिकॉर्ड किसी और द्वारा अपडेट नहीं किया गया हो)।अद्यतन कथन में नवीनतम पंक्तिवर्ती/टाइमस्टैम्प मान प्राप्त करना - एसक्यूएल सर्वर

मैं अद्यतन करने के बाद डेटा परत में बस एक प्राप्त कर रहा था लेकिन यह बहुत ही कुशल या पूरी तरह विश्वसनीय नहीं था।

निम्न तालिका के लिए:

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

मैंने कोशिश की:

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 

लेकिन किसी और के अद्यतन से rowverion मूल्य नहीं मिल रहा है की संभावना की वजह से पूरी तरह से खुश नहीं था। तब मैं rowversion दस्तावेज में (http://msdn.microsoft.com/en-us/library/ms182776.aspx/http://msdn.microsoft.com/en-us/library/ms177564.aspx) आउटपुट बयान में आए और इस की कोशिश की:

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 

यह अच्छी तरह से काम करता है। मेरे बहुत ही बुनियादी परीक्षणों में (केवल 10000 कॉल और समय चल रहा है) OUTPUT विकल्प में लगभग 40% अधिक समय लगता है लेकिन अभी भी आधा मिलीसेकंड से कम है। न तो सेट सांख्यिकी समय के साथ किसी भी मापने योग्य समय लिया।

मेरा सवाल है, क्या कोई इसे करने के लिए बेहतर/सरल तरीका जानता है?

मुझे उम्मीद थी कि मैं पहचान कॉलम के लिए SCOPE_IDENTITY() के समान उपयोग कर सकता हूं लेकिन ऐसा कुछ भी नहीं मिला। किसी को पता है कि मुझे कुछ याद आ रही है?

अग्रिम धन्यवाद।

+0

आउटपुट सम्मिलित करें पर किसी भी उत्पन्न मान प्राप्त करने के लिए जाने का रास्ता है (और है कि पहचान अगर आप मुझसे पूछें ... भी शामिल है) –

+0

ठीक है, उसके लिए धन्यवाद। किसी भी विशेष कारण से आप SCOPE_IDENTITY पर OUTPUT का पक्ष क्यों लेते हैं? –

+2

यह बहु-पंक्ति प्रविष्टियों के साथ काम करता है –

उत्तर

0

MSDN से:

@@ DBTS वर्तमान डेटाबेस के अंतिम रूप से प्रयुक्त टाइमस्टैम्प मान देता है। एक नया टाइमस्टैम्प मान उत्पन्न होता है जब टाइमस्टैम्प कॉलम वाली पंक्ति डाली जाती है या अपडेट की जाती है।

+2

धन्यवाद, मुझे इसके बारे में पता नहीं था। जब तक मैं गलत नहीं हूँ। यह इस परिदृश्य में भरोसेमंद काम नहीं करेगा क्योंकि यह प्रक्रिया के लिए स्कॉप्ड की बजाय डेटाबेस चौड़ा है (@@ पहचान के समान) (SCOPE_IDENTITY() के समान)। –

+0

आप सही हैं, यह एक नकारात्मक है। मुझे लगता है कि OUTPUT जाने का एकमात्र रास्ता है। –

0

आपकी समस्या यह है कि अद्यतन के बीच और किसी और का चयन करें पंक्तियों को अद्यतन करता है। तो जब आप अपने अपडेट स्टेटमेंट के बाद चयन करते हैं तो आपको वही मान नहीं मिलते हैं। यह गैर दोहराने योग्य पढ़ने का मुद्दा है। आपको अद्यतन कथन के साथ लॉकिंग संकेत (UPDLOCK) का उपयोग करना चाहिए। यह लॉक पाठकों को अनुमति देगा (जो साझा ताले हैं) लेकिन लेखकों को अवरुद्ध करेंगे। तो आपको अद्यतन के बाद एक ही पंक्ति मिल जाएगी। तो अपने संग्रहीत प्रक्रिया होना चाहिए -

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 
संबंधित मुद्दे