高效获取最大流水号(最大单号)的设计

业务背景:订单号由三部分组成:前缀+日期+流水,要求每天流水从001开始,连续,长度超出时自动进位。例如 Inv191125001 , Inv191125999 , Inv1911251000
系统设计:
获取最大单号的方法对所有单据类型通用,所以用动态拼接脚本获取
所有单据包含如下固定列:BillNo(单号),CreationTime(创建时间)
CreationTime必填且必须从数据库取默认值getdate()
新的单号 = 获取当前最大单号 + 1

获取最大单号实现如下:

DECLARE @Pre VARCHAR(64)
DECLARE @PreDate VARCHAR(8)

SET @Pre     = 'Inv'
SET @PreDate = Right(CONVERT(VARCHAR(100), DATEADD(dd, 0, getdate()), 112), 6)
SET @Pre     = @Pre + @PreDate

SELECT   TOP 1 BillNo
FROM     InvBillMaster
WHERE    CreationTime >= DATEADD(day, 0, datediff(day, 0, getdate())) AND BillNo LIKE @Pre + '%'
ORDER BY CreationTime DESC

代码解释:
1,拼接出今天的前缀 Pre = ‘Inv’ + ‘191125’
2,从今天的单据中过滤出前缀等于Pre的单据,获取最大CreationTime
3,获取最大CreationTime的单号

剩下的就是用最大单号解析出后三位整数+1得到新流水

主要有问题如下:
1,只要并发就会导致后一条记录插入时单号重复而报错,重新提交可以缓解,肯定不适合高并发场景
2,如果服务器时间发生修改,导致后插入的CreationTime小于前面的记录,将导致再也获取不到最大单号

不知道整个设计有没有问题

你可能感兴趣的:(高效获取最大流水号(最大单号)的设计)