Warning: file_get_contents(/data/phpspider/zhask/data//catemap/7/sql-server/26.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/sql-server-2008/3.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Sql server 在sql server中生成自动递增的varchar主键_Sql Server_Sql Server 2008 - Fatal编程技术网

Sql server 在sql server中生成自动递增的varchar主键

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

我想为每个单独的订单生成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   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更昂贵。