2014-09-26 148 views
1

我苦苦尋找SQL服務器更換爲select for update的作品。SQL服務器選擇更新

我有一個包含其用於下一個定單編號的列的主表。應用程序在此行上執行從更新中進行的選擇,讀取當前值(鎖定時)將此值添加一個值,然後更新該行,然後使用收到的數字。這個過程完全適用於我嘗試過的所有數據庫,但是對於似乎沒有任何選擇專用數據的過程的SQL Server。

我怎樣做一個鎖定的讀取和像從序列表中的下一個訂單號更新爲SQL服務器?

順便說一句,我知道我可以使用的東西像IDENTITY的cols和東西,要做到這一點,但在這種情況下,我必須從這個現有列讀取。獲得價值並加以利用,並以安全鎖定的方式進行操作,以避免2名用戶獲得相同的價值。

更新::

謝謝你,對於這種情況下的工作:)

DECLARE @Output char(30) 

UPDATE scheme.sysdirm 
SET @Output = key_value = cast(key_value as int)+1 
WHERE system_key='OPLASTORD' 

SELECT @Output 

我有另外一個地方,我做同樣的事情。我也讀取並鎖定了股票記錄。

SELECT STOCK 
FROM PRODUCT 
WHERE ID = ? FOR UPDATE. 

我然後做一些驗證和做

UPDATE PRODUCT SET STOCK = ? 
WHERE ID=? 

我不能只使用上面的方法在這裏,作爲值我更新是基於我的事情從我讀的股票做。但我需要確保在我這樣做的時候沒有其他人能夠囤積股票。再次,容易在其他數據庫的SELECT FOR UPDATE ...有沒有一個SQL Server的解決方法? :)

+1

你能後的現有代碼?我可能是錯的,但你可能只是想做到這一點:'UPDATE表SET字段=字段+ 1 WHERE東西' – jazzytomato 2014-09-26 09:32:29

回答

1

你可以簡單的做一個UPDATE也讀出新的價值到SQL Server變量:

DECLARE @Output INT 

UPDATE dbo.YourTable 
SET @Output = YourColumn = YourColumn + 1 
WHERE ID = ???? 

SELECT @Output 

因爲它是一個原子UPDATE聲明,這是對併發性問題(安全的,因爲只有一個連接可以在任何時候獲得更新鎖定)。想要同時獲得遞增值的潛在第二個會話必須等到第一個會話完成,從而獲得表中的下一個值。

+0

謝謝你。在這個例子中很有用。我有一個更棘手的一個(編輯原始帖子)這是再次簡單與SELECT FOR UPDATE,但不是那麼肯定你的解決方案適用於那個? – user1667016 2014-09-26 10:37:58

0

你可以使用UPDATE語句的OUTPUT子句的替代,雖然這會插入到表變量。

Create table YourTable 
(
    ID int, 
    YourColumn int 
) 

GO 

INSERT INTO YourTable VALUES (1, 1) 
GO 


DECLARE @Output TABLE 
( 
    YourColumn int 
) 

UPDATE YourTable 
SET YourColumn = YourColumn + 1 
OUTPUT inserted.YourColumn INTO @Output 
WHERE ID = 1 

SELECT TOP 1 YourColumn 
FROM @Output 

****編輯 如果你想確保沒有人可以更改數據您已經閱讀後,您可以使用可重複的讀取。您應該意識到,您所做的任何表的讀取都將被鎖定以進行更新(悲觀鎖定)並可能導致死鎖。您也可以在交易中起訴SELECT ... FROM TABLE (UPDLOCK)提示。

SET TRANSACTION ISOLATION LEVEL REPEATABLE READ 
BEGIN TRANSACTION 

SELECT STOCK 
FROM PRODUCT 
WHERE ID = ? 


..... 
... 

UPDATE Product 
SET Stock = nnn 
WHERE ID = ? 

COMMIT TRANSACTION