生成具有多个数字范围的唯一、复合、连续数字的方法



一个以PostgreSQL作为RDBMS的Java应用程序(通过普通JDBC使用(使用复合连续数字,如[CustomerNumber]-[Year]-[ConsecutiveNumber],其中[ConsecutiveNumber]为每个新客户和每个新年重新以1开头。格式化为字符串的数字看起来像10123-2018-0001

DB表中有一个UNIQUE约束,以确保客户编号、年份和连续编号的每个组合只能存在一次。

要分配的下一个空闲号码被确定为(Select Max(ConsecutiveNumber) From XYZ Where CustomerNumber=? And Year=?(+1。这只适用于锁定/同步以及一次只有一个服务器软件实例的事实(没有水平可扩展性,即有机会在前面有负载均衡器的多个服务器上运行应用程序(。

当然,可以忽略同步,但由于违反了唯一的约束,许多事务/提交都会失败。

你建议用什么方法来生成这样的复合唯一数?由于可能有无限的客户编号和年份,为每个客户编号/年份组合创建一个专用的DB SEQUENCE似乎是不可行的。

我想使用一个专用的Connection/事务来插入一个新生成的数字,以降低它在并发事务中被另一个线程/占用的概率。但是,如果实际业务事务由于任何原因没有提交,这将导致数据不一致("幽灵数字"(。

PostgreSQL具有"自动增量"类型SERIAL来生成新密钥。这将是插入新记录的明显方式,并且getGeneratedKeys()随后会询问这些密钥。

然而,在商业中,通常需要在一年内连续编号。

通常可以看到一个组合:一个生成的主键(用户永远看不到(和一个带有唯一性约束的自然键(可能而不是(。这允许在发布订单(打印、电子邮件(时添加自然密钥。此外,它还允许维修。

正如您自己评估的那样,"顺序密钥生成器"并非微不足道。但您可以将自然键拆分为复合键键:年份,序列号。这将简化SQL的使用。

我希望另一个答案能给出一个更有趣的实际解决方案。

最新更新