Sql server 在sql server中生成自动递增的varchar主键
我想为每个单独的订单生成varchar自动递增的主键订单id值,如下表所示 ‘O201307270001’ “O”表示订单,“20130727”表示日期为2013年7月27日,“0001”表示自动递增值 我想在新的一天开始时,从“1”开始重新启动上述id中的自动递增的最后4个数字 以下是我希望如何为在不同时间和日期下的订单生成订单ID的示例:Sql server 在sql server中生成自动递增的varchar主键,sql-server,sql-server-2008,Sql Server,Sql Server 2008,我想为每个单独的订单生成varchar自动递增的主键订单id值,如下表所示 ‘O201307270001’ “O”表示订单,“20130727”表示日期为2013年7月27日,“0001”表示自动递增值 我想在新的一天开始时,从“1”开始重新启动上述id中的自动递增的最后4个数字 以下是我希望如何为在不同时间和日期下的订单生成订单ID的示例: O201307270001 when date is like '2013-07-27 01:23:45.235' O201307270002 w
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'
请帮助我,我如何做到这一点我强烈建议您不要使用此varchar生成的代码作为表的主键,而是使用一个数值,并将此生成的字符串作为订单代码保存在单独的列中。这样,您就可以避免将来查询时的噩梦。您可以将此代码列标记为唯一,并获得相同的结果 关于如何生成订单代码,如果后面的逻辑没有自动增量或类似的逻辑那么基本,那么最好在系统的上层(如果有)执行此操作。您可以使用INSERT触发器,或者我建议使用CreateOrder存储过程来执行此操作 以下是您必须遵循的步骤: 计算当前日期前缀。'O'+CONVERTchar8,GETDATE,112 从表中选择最后一个订单号。从订单中选择MAXOrderNum 如果最后一个订单号具有当前日期前缀,请提取数字后缀,增加它,并将其附加到日期前缀。当@CurrentPrefix=LEFT@LastOrder,9,然后@CurrentPrefix+RIGHT'000'+CONVERTint,RIGHT@LastOrder, 4 + 1 否则,只需使用0001作为后缀。ELSE@CurrentPrefix+'0001' 使用生成的密钥执行插入。 试试这个
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))
正如其他答案已经指出的那样,这样做可能是一个坏主意,但是如果你想这样做,我相信这段代码应该能实现你想要的。我还没有尝试过所有角落的情况,但对于小测试数据,它提供了工作 我尝试过的一些测试数据:
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)
理想情况下,它应该封装在一个函数中,并且可能还使用锁定来避免同一个键被分发两次。我建议这样做,它有一个很大的优点:不读取目标表,并且随着表的增长,它将提供更好的性能 您必须创建一个短存储过程和一个参数表 只需调用存储过程,它将返回正确的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
在这里查看它创建表OrderNumberGenerator [ID]整数标识1,1, [New_ID]作为'O'+CONVERTvarchar
转到看看这个。有任何答案对您有帮助吗?如果订单在当天早些时候被删除,则选择“计数*无效”。是的。这里有这样一个问题。谢谢你,盖布。我没有注意到varchar可以用作主键,对于PK来说,这个orderNumber不是一个坏的选择。键是与业务相关的,当涉及到索引和性能问题时,实际上并不是同一个问题。即使我相信这个列也可以用作聚集索引,因为它是按顺序生成的VarChar可以用作主键,当然,我不认为它们不能。键是与业务相关的,我不同意,我想在大多数情况下,我们使用键作为业务实体的标识符,但它们不一样,就像在这个用户表中:UserId-Key,与业务逻辑Email-Identifier相关与否,与BL firstname相关只是说,键是逻辑关系,而索引是关于存储和性能的。你在回答中混合了这两个概念我的回答中从来没有提到过索引,是的。也许未来查询的噩梦会让你想到索引,但我指的是必须匹配相关表中的顺序代码,保存自动增量值0001的锁似乎一天只能放置9999个,或者必须使用select*from Orders,其中古怪的Orders ID在。。。,此查询类型最终按WeirdOrderId对结果排序。您可以在此列上创建和维护所有所需的索引,但这总是比处理简单且众所周知的数字id更昂贵。