业务背景:订单号由三部分组成:前缀+日期+流水,要求每天流水从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 --前缀+6位日期
SET @Today = DATEADD(day, 0, datediff(day, 0, getdate())) --当天0点整
SELECT TOP 1 BillNo
FROM InvBillMaster
WHERE CreationTime >=@Today AND BillNo LIKE @Pre + '%' --在CreationTime列添加聚集索引
ORDER BY CreationTime DESC, BillNo DESC
代码解释:
1,拼接出今天的前缀 Pre = ‘Inv’ + ‘191125’
2,从今天的单据中过滤出前缀等于Pre的单据,获取最大CreationTime
3,获取最大CreationTime的单号
剩下的就是用最大单号解析出后三位整数+1得到新流水
主要有问题如下:
1,不适合高并发场景: 只要并发就会导致后一条记录插入时单号重复而报错,重新提交可以解决
2,如果服务器时间发生修改,导致后插入的CreationTime小于前面的记录,将导致再也获取不到最大单号
不知道整个设计有没有问题