我有一个SQL Server 2005数据库。 Table A
中包含一个标识列以及另一个跨越多行的手动Id
列。第二个id
列格式为'0000000098'
,必须是字符串。我无法更改数据类型。
Function A
获取最大ID
列值,将其递增1,转换为字符串。
我的存储过程获取新ID,然后使用此ID进行多次插入。
如何在更新发生之前阻止两个客户端运行存储过程并获取相同的ID?我可以将表a从读取锁定,直到proc处理完成或者是否有更有效的方法?
如果我可以更改数据类型和/或结构,那将很容易,但我不能。
答案 0 :(得分: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在更新锁定下运行,因此没有两个进程可以同时运行它。我认为你根本不需要任何进一步的锁定 - 绝对不是一个完整的锁定....
答案 1 :(得分:0)
是的,您可以锁定表格。你需要做事务中的所有事情,当你第一次阅读表时,你可以使用提示(updlock,holdlock)或甚至(TABLOCKX)进行独占连续锁定