Warning: file_get_contents(/data/phpspider/zhask/data//catemap/3/sql-server-2005/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Sql server 2005 SQL Server函数-防止重复_Sql Server 2005_Stored Procedures_Sql Function_Record Locking - Fatal编程技术网

Sql server 2005 SQL Server函数-防止重复

Sql server 2005 SQL Server函数-防止重复,sql-server-2005,stored-procedures,sql-function,record-locking,Sql Server 2005,Stored Procedures,Sql Function,Record Locking,我有一个SQLServer2005数据库表A中有一个标识列,以及另一个手动Id列,该列跨越多行。第二个id列的格式为'00000000 98',必须是字符串。我无法更改数据类型 函数A获取最大ID列值,将其递增1,转换为字符串 我的存储过程获取新ID,然后使用该ID执行若干次插入 如何防止两个客户端在更新之前运行存储过程并获得相同的ID?我可以从读取锁定表a,直到proc完成处理,还是有更有效的方法 如果我可以更改数据类型和/或结构,这将很容易,但我不能。是的,您可以锁定表。您需要在事务中执行所

我有一个SQLServer2005数据库<代码>表A中有一个标识列,以及另一个手动
Id
列,该列跨越多行。第二个
id
列的格式为
'00000000 98'
,必须是字符串。我无法更改数据类型

函数A
获取最大
ID
列值,将其递增1,转换为字符串

我的存储过程获取新ID,然后使用该ID执行若干次插入

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


如果我可以更改数据类型和/或结构,这将很容易,但我不能。是的,您可以锁定表。您需要在事务中执行所有操作,当您第一次读取表时,您可以在表上放置一个带有提示的独占连续锁(updlock、holdlock)甚至(TABLOCKX)

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

如果您可以将函数表述为单个
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 ..........
如果您需要一个两步流程-
更新之前选择
,那么我会在
选择
上使用
和(UPDLOCK)
提示

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

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

如果您可以将函数表述为一个
UPDATE
语句,那么就不需要显式锁定-
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 ..........
如果您需要一个两步流程-
更新之前选择
,那么我会在
选择
上使用
和(UPDLOCK)
提示

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

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

这是个好主意。我想知道是否有两个人同时运行脚本,它是否可能1)运行函数并获取下一个ID 2)下一个人获取下一个ID 3)第一个人在第二个人获取下一个ID后运行insert语句。。。导致两者具有相同的ID。这是可能的,还是因为它正在执行插入操作,它会自动锁定该表?它是用于会计特定表的,所以我不能让它复制ID的。。。会计噩梦比任何其他噩梦都糟糕没关系,我只是重读了你的帖子。。。有道理,谢谢!(周围的孩子不能集中注意力)这是个好主意。我想知道是否有两个人同时运行脚本,它是否可能1)运行函数并获取下一个ID 2)下一个人获取下一个ID 3)第一个人在第二个人获取下一个ID后运行insert语句。。。导致两者具有相同的ID。这是可能的,还是因为它正在执行插入操作,它会自动锁定该表?它是用于会计特定表的,所以我不能让它复制ID的。。。会计噩梦比任何其他噩梦都糟糕没关系,我只是重读了你的帖子。。。有道理,谢谢!(周围的孩子——无法集中注意力)