2009-12-23 149 views
2

如果我要選擇尚未處理表中的所有記錄,然後更新這些記錄來反映,他們已被處理,我會做到以下幾點:T-SQL交易並鎖定表

SELECT * FROM [dbo].[MyTable] WHERE [flag] IS NULL; 
UPDATE [dbo].[MyTable] SET [flag] = 1 WHERE [flag] IS NULL; 

如何確保UPDATE僅對剛剛選擇的記錄起作用,即,防止任何可能添加了[flag] = NULL且在我的SELECT之後但在另一個進程的UPDATE之前添加的記錄的UPDATE?我可以在交易中包裝這兩個陳述嗎?我必須在桌子上放一把鎖嗎?

回答

6

單一調用,使用OUTPUT子句不需要事務。

XLOCK專門鎖定行停止併發讀取(如尋找空的行另一個進程)

UPDATE dbo.MyTable WITH (XLOCK) 
SET flag = 1 
OUTPUT INSERTED.* 
WHERE flag IS NULL; 
+1

SQL Server的最早版本支持'OUTPUT'子句? – 2009-12-23 07:38:57

+1

SQL Server 2005,這應該是一個公平的假設(幾乎)在2010年... – gbn 2009-12-23 07:40:26

+0

..並給出OP也使用SSIS也基於其他問題。 – gbn 2009-12-23 07:41:19

2

可以將這兩個語句用read_committed或更受限制的作用域包裝在事務中。它有點貴,可能會導致其他問題。 King的解決方案更加可行。

3

用途:

SELECT * 
    FROM [dbo].[MyTable] (UPDLOCK) 
WHERE [flag] IS NULL; 

UPDATE [dbo].[MyTable] 
    SET [flag] = 1 
WHERE [flag] IS NULL; 

有關鎖定提示的詳細信息:

+1

+1。請注意,這需要位於更新鎖進行更新語句的事務中。 – womp 2009-12-23 03:22:31

+0

儘管SQL Server 2005不需要2個語句+ – gbn 2009-12-23 07:33:11

5

使用OUTPUT子句返回從自我更新的結果集:

UPDATE [dbo].[MyTable] 
SET [flag] = 1 
OUTPUT INSERTED.* 
WHERE [flag] IS NULL;