为什么此SQL存储过程中的自然ID生成会产生重复?

时间:2010-12-10 05:56:37

标签: sql-server stored-procedures

我正在使用存储过程将productd的字母数字值递增1。我的程序将值增加到10个记录,一旦达到10,说PRD0010 ...不再增加它...但是,问题是它重复 对于每个SP呼叫,PRD0010 ..的值相同。

这可能是什么原因?

create table tblProduct
(
       id varchar(15)
)

insert into tblProduct(id)values('PRD00')

create procedure spInsertInProduct
AS
Begin

    DECLARE @PId VARCHAR(15)
    DECLARE @NId INT
    DECLARE @COUNTER INT
    SET @PId = 'PRD00'
    SET @COUNTER = 0
    SELECT @NId = cast(substring(MAX(id), 4, len(MAX(id))) as int)
    FROM tblProduct group by left(id, 3) order by left(id, 3)
    --here increse the vlaue to numeric id by 1
    SET @NId = @NId + 1
    --GENERATE ACTUAL APHANUMERIC ID HERE
    SET @PId = @PId + cast(@NId AS VARCHAR)
    INSERT INTO tblProduct(id)values (@PId)

END

2 个答案:

答案 0 :(得分:3)

更改

SELECT @NId = cast(substring(MAX(id), 4, len(MAX(id))) as int)  
    FROM tblProduct group by left(id, 3) order by left(id, 3)

SELECT  TOP 1
        @NId = cast(substring(id, 4, len(id)) as int)
FROM tblProduct  order by LEN(id) DESC, ID DESC

你必须记住那个

PRD009

总是大于

PRD0010

PRD001

总而言之,我认为你的做法是错误的。

您的价值观将是

PRD00
PRD001
...
PRD009
PRD0010
PRD0011
...
PRD0099
PRD00100

这将使整理变成一场噩梦。

答案 1 :(得分:0)

除了旁观者的分析,你还有一个并发问题。

简单的解决方法是在proc的开头添加:

SET TRANSACTION ISOLATION LEVEL SERIALIZABLE
BEGIN TRANSACTION

最后添加COMMIT。否则,此存储过程的两个调用者将从您的表中获得相同的MAX / TOP 1值,并插入相同的值。

此外,您可以而且应该通过向此列添加密钥来阻止这些重复项存在。如果此表上已有PRIMARY KEY,则可以使用UNIQUE约束添加其他键。无论发生什么编程错误,这都将防止将来发生重复。 E.g。

ALTER TABLE tblProduct ADD CONSTRAINT UQ_Product_ID UNIQUE (ID)