1

我有一个 SQL Server 2005 数据库。Table A其中有一个标识列以及另一个Id跨越多行的手动列。第二id列的格式为,'0000000098'并且必须是字符串。我无法更改数据类型。

Function A获取最大ID列值,将其加一,转换为字符串。

我的存储过程获取新 ID,然后使用此 ID 进行多次插入。

如何防止两个客户端在更新发生之前运行存储过程并获得相同的 ID?我可以从读取中锁定表 a 直到 proc 完成处理还是有更有效的方法?

如果我可以更改数据类型和/或结构,那将很容易,但我不能。

4

2 回答 2

1

如果您可以将您的函数表述为单个UPDATE语句,则不需要显式锁定 - 该UPDATE语句将需要一个更新锁 ( U),这是独占的,例如,没有两个读取器可以同时在同一行上获得更新锁。

UPDATE dbo.TableA
SET ManualID = CAST(CAST(ManualID AS INT) + 1 AS VARCHAR(20))
OUTPUT Inserted.ManualID  -- return the newly inserted manual ID for your use
WHERE ..........

如果您需要一个两步过程 -SELECT之前UPDATE- 然后我会使用WITH (UPDLOCK)提示SELECT

DECLARE @OldManualID VARCHAR(20)

BEGIN TRANSACTION

SELECT @OldManualID = ManualID 
FROM dbo.TableA WITH (UPDLOCK)
WHERE........

-- do something with that manual ID

UPDATE dbo.TableA
SET ManualID = (new value of ManualID)
WHERE ..........

COMMIT TRANSACTION

在这两种情况下,由于单个 UPDATE 或 SELECT/UDPATE 在更新锁下运行,因此没有两个进程可以同时运行它。我认为您根本不需要任何进一步的锁定-绝对不是全表锁定....

于 2011-12-21T06:02:01.143 回答
0

是的,您可以锁定桌子。您需要在事务中执行所有操作,当您第一次读取表时,您可以在其上放置一个带有提示(updlock、holdlock)甚至(TABLOCKX)的排他连续锁

于 2011-12-21T03:31:01.537 回答