如果我需要根据存储过程中相对复杂的WHERE
子句从表列(恰好是主键列)中SELECT
一个值,并且然后我想在没有任何其他并发存储过程 SELECT
ing 相同记录的情况下更新该记录,它是否像使用事务一样简单?还是我还需要将隔离提高到可重复读取?
看起来像这样:
Alter Procedure Blah
As
Declare @targetval int
update table1 set field9 = 1, @targetval = field1 where field1 = (
SELECT TOP 1 field1
FROM table1 t
WHERE
(t.field2 = 'this') AND (t.field3 = 'that') AND (t.field4 = 'yep') AND (t.field9 <> 1))
return
然后我在我的程序中获取我的 targetval,这样我就可以对其进行处理,同时我不必担心其他工作线程获取相同的 targetval。
我在这里说的是 SQL 2000、SQL 2005 和 SQL 2008。
最佳答案
将 ROWLOCK,UPDLOCK
添加到子查询中应该可以做到这一点。
ALTER PROCEDURE Blah
AS
DECLARE @targetval INT
UPDATE table1
SET field9 = 1,
@targetval = field1
WHERE field1 = (SELECT TOP 1 field1
FROM table1 t WITH (rowlock, updlock)
WHERE ( t.field2 = 'this' )
AND ( t.field3 = 'that' )
AND ( t.field4 = 'yep' )
AND ( t.field9 <> 1 ))
RETURN
已更新
目前接受的这个问题的答案不使用updlock
。我完全不相信这会奏效。据我在这种类型的带有子查询的查询测试中所见,SQL Server 只会为子查询获取 S
锁。然而,有时子查询会被优化掉,所以这种方法可能看起来像查询 2 中那样工作。
测试脚本 - 设置
CREATE TABLE test_table
(
id int identity(1,1) primary key,
col char(40)
)
INSERT INTO test_table
SELECT NEWID() FROM sys.objects
查询 1
update test_table
set col=NEWID()
where id=(SELECT top (1) id from test_table )
查询2
update test_table
set col=NEWID()
where id=(SELECT max(id) from test_table)
关于sql - 在更新记录时锁定记录的最佳方法是什么?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/4595643/