如果我需要SELECT
基于存储过程中相对复杂的WHERE
子句的表列中的值(恰好是主键列),然后我想要更新记录没有任何其他并发存储过程SELECT
相同的记录,是否只是使用事务一样简单?或者我是否还需要将隔离提升到可重复读取?
看起来像这样:
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。
答案 0 :(得分:2)
将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
update test_table
set col=NEWID()
where id=(SELECT top (1) id from test_table )
update test_table
set col=NEWID()
where id=(SELECT max(id) from test_table)