2

我想为每个单独的订单生成 varchar 自动递增的主键(订单 ID)值,如下面的格式所示。

'O201307270001'

“O”表示订单, “20130727”表示日期(2013 年 7 月 27 日), “0001”表示自动递增值

我想在新的一天开始时重新启动自动递增的数字(上面 id 中的最后 4 个数字)从“1”开始。

下面是我希望如何为在不同时间和日期下的订单生成订单 ID 的示例:

O201307270001   when date is like '2013-07-27 01:23:45.235'
O201307270002   when date is like '2013-07-27 03:12:22.212'
.
.
.
O201307270040   when date is like '2013-07-27 11:34:56.189'
.
.
//Now when new day starts:
O201307280001   when date is like '2013-07-28 00:00:00.000'
O201307280002   when date is like '2013-07-28 00:13:05.000'

请帮助我,我该怎么做

4

6 回答 6

2

这是我的建议,它具有不读取目标表的(相当大的:))优势,并且随着表的增长将提供更好的性能。

您必须创建一个简短的存储过程和一个参数表。

只需调用存储过程,它就会返回正确的 Id :

DECLARE @NewOrderId AS CHAR(13)

EXEC usp_NewOrderId @NewOrderId OUTPUT

SELECT @NewOrderId

这是您需要创建的:

CREATE TABLE OrderNumberGenerator (
  Id INTEGER IDENTITY(1,1),
  CreatedDate DATE DEFAULT(GETDATE()) 
 )
GO

CREATE PROCEDURE usp_NewOrderId 
(@NewOrderIdOut char(13) OUTPUT ) 
AS 
BEGIN

   IF EXISTS (SELECT 1 FROM OrderNumberGenerator WHERE CreatedDate <> CAST(GETDATE() AS DATE) )
    TRUNCATE TABLE OrderNumberGenerator --restart the counter everyday :)

  INSERT INTO OrderNumberGenerator DEFAULT VALUES

  SELECT @NewOrderIdOut = 
  'O' +
  CONVERT(CHAR(8), GETDATE(), 112) +
  RIGHT( '000' + CAST(SCOPE_IDENTITY() AS VARCHAR(4)) ,  4 ) 

END

在这里查看http://sqlfiddle.com/#!3/fdb91/4

于 2013-07-27T16:28:08.277 回答
0

我强烈建议您不要将此 varchar 生成的代码用作表的主键,而是使用数值并将此生成的字符串作为订单代码保存在单独的列上(这将使您远离未来查询的噩梦)。您可以将此代码列标记为“唯一”并获得相同的结果。

关于如何生成订单代码,如果背后的逻辑不像自动增量或类似的那样基本,最好在系统的上层(如果有的话)有这个donde。

于 2013-07-27T16:06:44.153 回答
0

创建表 OrderNumberGenerator ( [ID] INTEGER IDENTITY(1,1), [New_ID] AS 'O'+CONVERT(varchar) ) GO

于 2013-12-11T07:08:21.463 回答
0

您可以使用INSTEAD OF INSERT触发器或我推荐的CreateOrder存储过程来执行此操作。

以下是您必须遵循的步骤:

  1. 计算当前日期前缀。'O' + CONVERT(char(8), GETDATE(), 112)
  2. 从表中选择最后一个订单号。SELECT MAX(OrderNum) FROM Order
  3. 如果最后一个订单号具有当前日期前缀,则提取数字后缀,将其递增,并将其附加到日期前缀。WHEN @CurrentPrefix = LEFT(@LastOrder, 9) THEN @CurrentPrefix + RIGHT('000' + (CONVERT(int, RIGHT(@LastOrder, 4)) + 1))
  4. 否则,仅用0001作后缀。ELSE @CurrentPrefix + '0001'
  5. 使用生成的密钥执行插入。
于 2013-07-27T16:17:33.127 回答
0

尝试这个

DECLARE @autoInc VARCHAR(25)
SET @autoInc='O'+(SELECT convert(varchar, getdate(), 112))+
               CAST(((SELECT COUNT(*) 
                     FROM table 
                 WHERE autoColumn like 'O'+(SELECT convert(varchar, getdate(),112))+'%') 
                       +1 ) AS VARCHAR(5))
于 2013-07-27T16:22:20.100 回答
0

正如其他答案已经指出的那样,这样做可能是一个坏主意,但如果你想无论如何这个代码应该完成你想要的我相信。我还没有尝试过所有极端情况,但对于提供的小测试数据来说它是有效的。

我尝试的一些测试数据:

declare @tab table (pk char(13))
insert @tab values ('O201307270001')
insert @tab values ('O201307270002')
insert @tab values ('O201307270003')
insert @tab values ('O201307278999')
insert @tab values ('O201307280001')
insert @tab values ('O201307280002')
insert @tab values ('O201307290001')

然后是实际代码:

SELECT 
  CASE ISNULL(MAX(RIGHT(pk,4)),0) 
    WHEN 0 THEN 'O' + CONVERT(CHAR(8),GETDATE(),112) + '0001' 
   ELSE 'O' + CONVERT(CHAR(8),GETDATE(),112) + RIGHT(CAST(MAX(RIGHT(pk,4)) + 10001 AS CHAR(5)),4) END 
FROM @tab 
WHERE SUBSTRING(pk,2,8) = CONVERT(CHAR(8),GETDATE(),112)

理想情况下,它应该包含在一个函数中,并且可能也使用锁定来避免相同的密钥被分发两次。

于 2013-07-27T16:22:37.387 回答