在我的SQL Server 2005数据库中,我在表RMA_Number
中有一个列RMA
,其数据类型为char(10)。
值越来越多,格式为RMA0002511
。在插入时增加最高数字的最快方法是什么?
我的第一个方法是:
SELECT TOP (1) RMA_Number
FROM RMA
WHERE (RMA_generated = 1)
ORDER BY Creation_Date DESC
但这很容易出错,因为某种程度上可能更高的RMA_Number具有更早的创建日期。作为解决方法,按主键排序:
SELECT TOP (1) RMA_Number
FROM RMA
WHERE (RMA_generated = 1)
ORDER BY idRMA DESC
但也许这也是一个可能的错误来源。
从逻辑上讲,最好的方法是ORDER BY RMA_Number DESC
。
但是因为我不确定这是否总能给出正确的结果,并认为如果记录数增加,排序char列会变慢,我选择按Date列排序。
所以,
SELECT MAX( RMA_Number ) FROM RMA
获得最高数字(性能和准确性)int
列并在应用程序中格式化数字,我是否应该继续使用主键进行排序?修改:
我想我必须澄清一些我没有提到过的事情。每次插入时都不会生成RMA_Number。所以也许有很多没有数字的记录。 Martin使用主键来构建数字。那将是一个问题,因为差距太大了。
提前谢谢。
答案 0 :(得分:7)
最快和最安全(并发)的方法是不存储RMA000...
前缀。
只需创建一个整数标识列,并通过计算列添加前缀。
create table #RMA
(
id int identity(2511,1) primary key,
RMA_Number as 'RMA' + RIGHT('000000' + CAST(id as varchar(7)),7)
)
insert into #RMA
default values
select * from #RMA
或者在新信息之后,并非所有记录都有RMA_Number
,您可以将此方法用于非阻塞,高效且并发的安全解决方案。
CREATE TABLE dbo.Sequence(
val int IDENTITY (2511, 2) /*Seed this at 1 + whatever your current max value is*/
)
GO
/*Call this procedure to get allocated the next sequence number to use*/
CREATE PROC dbo.GetSequence
@val AS int OUTPUT
AS
BEGIN TRAN
SAVE TRAN S1
INSERT INTO dbo.Sequence DEFAULT VALUES
SET @val=SCOPE_IDENTITY()
ROLLBACK TRAN S1 /*Rolls back just as far as the save point to prevent the
sequence table filling up. The id allocated won't be reused*/
COMMIT TRAN
答案 1 :(得分:3)
首先,你正在看一个严重的竞争条件。
当我们在我们使用的项目上需要这个时,我们有一个单独的表,其中存储了当前值,并且有一个函数来生成下一个。我们实现了锁定以保持多次调用以获取下一个号码。我记得,这是因为我们必须使用字母数字标识号(该函数负责复杂的递增)。
但是,我最喜欢@ Martin的解决方案:使用和IDENTITY
字段。您可以按照他的建议删除前缀,也可以将其从列中删除,并在从表中SELECT
时将其重新附加。