SQL Server选择更新

时间:2014-09-26 09:22:24

标签: sql-server sql-server-2008 select locking

我正在努力找到适用于select for update的SQL Server替代品。

我有一个主表,其中包含一个用于下一个订单号的列。应用程序对此行执行从更新中选择,读取当前值(锁定时)将此值加1,然后更新该行,然后使用它接收的数字。这个过程适用于我尝试过的所有数据库,但是对于SQL Server来说似乎没有任何选择专用数据的过程。

如何从序列表中锁定读取和更新下一个订单号的内容是SQL Server?

顺便说一句,我知道我可以使用像IDENTITY cols和stuff这样的东西来做这件事,但在这种情况下我必须阅读这个现有专栏。获取价值并加入,并以安全锁定的方式进行,以避免2个用户获得相同的价值。

UPDATE ::

谢谢,这适用于这种情况:)

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解决方法? :)

2 个答案:

答案 0 :(得分:1)

您可以简单地执行UPDATE并将新值读入SQL Server变量:

DECLARE @Output INT

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

SELECT @Output

由于它是一个原子UPDATE语句,因此可以安全地防止并发问题(因为在任何给定时间只有一个连接可以获得更新锁)。想要同时获得递增值的潜在第二个会话必须等到第一个会话完成,从而从表中获取下一个值。

答案 1 :(得分:0)

作为替代方法,您可以使用OUTPUT语句的UPDATE子句,尽管这会插入到表变量中。

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