char列上的MAX / ORDER BY

时间:2010-12-01 14:34:26

标签: sql-server performance sql-server-2005 database-design sql-order-by

在我的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列排序。

所以,

  1. 以char(10)-column(性能和准确度)排序是个好主意吗?
  2. SELECT MAX( RMA_Number ) FROM RMA获得最高数字(性能和准确性)
  3. 会更好吗?
  4. 如果前两个点错误或者我应该使用int列并在应用程序中格式化数字,我是否应该继续使用主键进行排序?
  5. 修改

    我想我必须澄清一些我没有提到过的事情。每次插入时都不会生成RMA_Number。所以也许有很多没有数字的记录。 Martin使用主键来构建数字。那将是一个问题,因为差距太大了。

    提前谢谢。

2 个答案:

答案 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时将其重新附加。