2015-09-02 38 views
0

我正在嘗試編寫一個存儲過程,該過程讀​​取表的特定行中的列,然後使用新值更新該列。原始。返回。從行中選擇一列並將該列更新爲另一個值

我希望它鎖定其他人的行,直到我完成。過程是什麼?

我有類似

CREATE PROCEDURE [dbo].[aptc_Prt_NextDocumentNumberGet] 
    (@_iFormatConfigID INT, @_oNextDocumentNumber FLOAT OUTPUT) 
AS 
BEGIN 
    DECLARE @FrameworkConfig XML 

    SET @_oNextDocumentNumber = - 1 

    DECLARE @NewNextDocumentID FLOAT 

    SELECT 
     @_oNextDocumentNumber = FrameworkConfig.value('(/Parameters/Parameter[@Name="NextDocNo.NextDocumentNumber"])[1]', 'float') 
    FROM 
     [ttcPrtFormatConfig] WITH (ROWLOCK) 
    WHERE 
     FormatConfigID = @_iFormatConfigID 

    -- Select the Next Doc num out of the xml field 
    -- increment appropriate control and set output 
    IF @_iFormatConfigID IS NOT NULL 
    BEGIN 
     -- set what will be the "next" doc number after we add this current txn 
     IF (ABS(@_oNextDocumentNumber - 99999999999999999) < 0.0001) 
     BEGIN 
      SELECT @NewNextDocumentID = 1 
     END 
     ELSE 
     BEGIN 
      SELECT @NewNextDocumentID = @_oNextDocumentNumber + 1 
     END 

     UPDATE [ttcPrtFormatConfig] 
     WITH (ROWLOCK) 

     SET FrameworkConfig.modify(' 
      replace value of 
       (/Parameters/Parameter[@Name="NextDocNo.NextDocumentNumber"]/text())[1] 
       with sql:variable("@NewNextDocumentID")') 
     WHERE FormatConfigID = @_iFormatConfigID 
    END 
END 
+0

您只需要一個事務和UPDLOCK HOLDLOCK。看到我的回答 –

回答

1

這應該讓你接近你想要什麼。

DECLARE @MyValue INT 

--You need a transaction so that the scope of your lock is well defined 
BEGIN TRANSACTION 
BEGIN TRY 

    --Get the value you are interested in, This select will lock the row so other people will not even be able to read it until you are finished!!!!! 
    SELECT  @MyValue = MyValue 
    FROM  MyTable WITH (UPDLOCK HOLDLOCK) 
    WHERE  MyValue = SomeValue 

    --Do your checks and updates. You can take as long as you like as you are the only person who can do a read or update of this data. 
    IF 
    BEGIN 
     UPDATE MyTable 
    END 

--Make sure you commit or rollback! this will release the lock 
END TRY 
BEGIN CATCH 

    --Oh no bad stuff! give up and put it back to how it was 
    PRINT ERROR_MESSAGE() + N' Your message here' 

    --Check there is a transaction that we can rollback 
    IF @@TRANCOUNT > 0 
    BEGIN 
     ROLLBACK; 
    END 

    --You may want to return some error state and not throw! 
    THROW; 
    --RETURN -1 --(for example) 

END CATCH; 

--yay it all worked and your lock will be released 
COMMIT 

--Do what you like with the old value 
RETURN @MyValue 
+0

這是一個正確但不完整的答案。請使用開始try try end塊來封裝整個代碼塊,並且在開始catch時,您可能希望對@@ TRANCOUNT進行代碼檢查,然後再進行回滾。 –

+0

好點,我試圖不渾水,只是堅持基礎知識。但是我已經做了更改以提供完整的畫面 –

+0

檢查@@ trancount是SQL Server幫助的一個示例,它使用它來捕獲以確定是否需要回滾。它是一個非常好的通用設計模式。如果@@ trancount大於0,您只想發佈回滾。爲什麼不包含它? –

相關問題