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

时间:2018-07-18 23:43:42

标签: java database postgresql sequence

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

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

要分配的下一个空闲号码为({Select Max(ConsecutiveNumber) From XYZ Where CustomerNumber=? And Year=?)+ 1。仅由于锁定/同步以及一次仅存在一个服务器软件实例(没有水平可伸缩性,即没有机会在前面有负载均衡器的情况下在多台服务器上运行该应用程序)的事实,这才起作用。

当然可以只保留同步,但由于违反唯一约束,很多事务/提交都会失败。

您建议使用哪种方法来生成这种复合唯一数字? 由于可以有无限的客户数量和年份,因此为每个客户数量/年份组合创建专用的数据库序列似乎是不可行的。

我想到了将专用的Connection /事务仅用于新生成的数字的INSERT,以减少已被另一个线程/在并发事务中使用的可能性。但是,如果由于任何原因未提交实际的业务交易,这将导致数据不一致(“虚拟数字”)。

1 个答案:

答案 0 :(得分:0)

PostgreSQL具有“自动递增”类型SERIAL以生成新密钥。 这将是插入新记录的明显方法,然后getGeneratedKeys()随后询问这些键。

然而,在企业中,经常需要在一年之内进行如此连续的编号。

通常会看到一种组合:一个生成的主键(用户从未看到过)和一个具有唯一性约束的自然键(可能是 not )。这样可以在下达订单(打印,通过电子邮件)时添加自然键。此外,它还可以维修。

在您评估自己时,“顺序密钥生成器”并不容易。但是您可以将自然键分为 compound 键的部分:年份,序列号。 这样可以简化SQL的使用。

我希望其他答案能够提供一个更有趣的实用解决方案。