2011-04-04 94 views
1

沒有「干擾」更新行我有這個存儲過程返回值和SQL Server

CREATE PROCEDURE spGrabSerial 
    @serial nvarchar(16) output 
AS 
BEGIN 
    SET NOCOUNT ON; 
    set @serial = (SELECT top 1 serial from tblSerial) 
    update tblSerial set InUse = 1 where serial = @serial 
END 

我怎樣才能確保沒有其他的程序爭奪相同的序列中選擇和更新之間?

+1

不要忘記檢查串行未使用:'從tblSerial其中INUSE <> 1' – Johan 2011-04-04 09:33:08

+0

呵呵選擇頂部1個串口。我只是看到它自己,小細節;) – 2011-04-04 10:16:35

回答

6

假設SQL Server 2005+可以使用OUTPUT子句在一個原子操作中完成它(請參閱Using tables as Queues)。

;with cte as (
    select top(1) 
     serial, InUse 
    from tblSerial with (rowlock, readpast) 
    where InUse <> 1 
    order by serial 
    ) 
update cte 
set InUse = 1 
output inserted.serial 

編輯就被提醒的這樣的一種方式,可以直接分配給output參數不使用OUTPUT條款都沒有。

with cte as (
    select top(1) 
     serial, InUse 
    from tblSerial with (rowlock, readpast) 
    where InUse <> 1 
    order by serial 
    ) 
update cte 
set InUse = 1, @serial = serial 
+0

不錯。如何將inserted.serial填充到@serial輸出變量中?我以爲SP的只能返回數值? – 2011-04-04 10:21:53

+1

如果你需要將它分配給一個'OUTPUT'變量,並且不能直接使用它,那麼你需要'OUTPUT INTO @ tablevariable'然後從那裏分配。出於某種原因,沒有語法直接從'OUTPUT'分配標量變量。 – 2011-04-04 10:35:36

+0

適合我:) – 2011-04-04 10:49:30

1

確保在事務隔離級別「可重複讀」運行:

set transaction isolation level repeatable read 

然後在一個事務中運行存儲過程,它會從其他的變化中分離出來。