温柔,我是一个SQL新手。我有一个名为autonumber_settings的表,如下所示:
Prefix | AutoNumber
SO | 112320
CA | 3542
每当创建新的销售行时,都会调用一个存储过程,该过程从“SO”行读取当前的自动编号值,然后递增该数字,更新该行,并从存储过程返回该数字。存储过程如下:
ALTER PROCEDURE [dbo].[GetAutoNumber]
(
@type nvarchar(50) ,
@out nvarchar(50) = '' OUTPUT
)
as
set nocount on
declare @currentvalue nvarchar(50)
declare @prefix nvarchar(10)
if exists (select * from autonumber_settings where lower(autonumber_type) = lower(@type))
begin
select @prefix = isnull(autonumber_prefix,''),@currentvalue=autonumber_currentvalue
from autonumber_settings
where lower(autonumber_type) = lower(@type)
set @currentvalue = @currentvalue + 1
update dbo.autonumber_settings set autonumber_currentvalue = @currentvalue where lower(autonumber_type) = lower(@type)
set @out = cast(@prefix as nvarchar(10)) + cast(@currentvalue as nvarchar(50))
select @out as value
end
else
select '' as value
现在,还有另一个过程访问复制订单的同一个表,同时复制标题和行。有时,复制会导致重复的行号。这是一个程序:
BEGIN TRAN
IF exists
(
SELECT *
FROM autonumber_settings
WHERE autonumber_type = 'SalesOrderDetail'
)
BEGIN
SELECT
@prefix = ISNULL(autonumber_prefix,'')
,@current_value=CAST (autonumber_currentvalue AS INTEGER)
FROM autonumber_settings
WHERE autonumber_type = 'SalesOrderDetail'
SET @new_auto_number = @current_value + @number_of_lines
UPDATE dbo.autonumber_settings
SET autonumber_currentvalue = @new_auto_number
WHERE autonumber_type = 'SalesOrderDetail'
END
COMMIT TRAN
关于为什么这两个程序似乎不能很好地结合起来的任何想法,偶尔会给出从头开始创建的相同行号作为复制创建的行。
答案 0 :(得分:0)
这是竞争条件或您的自动编号。两个执行有可能在将新值写回数据库之前读出相同的值。
解决此问题的最佳方法是使用标识列并让SQL服务器处理自动编号分配。
除非您可以使用sp_getapplock序列化对autonumber_settings的访问权限。
答案 1 :(得分:0)
您可以对选择使用可重复读取。这将锁定行并阻止其他过程的选择,直到您更新值并提交。
在每个选择的from子句后插入WITH(REPEATABLEREAD,ROWLOCK)。