我正在努力找到适用于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解决方法? :)
答案 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