有一种方法可以让主键 ID 没有任何间隙
Posted
技术标签:
【中文标题】有一种方法可以让主键 ID 没有任何间隙【英文标题】:There a way to have primary key ids without any gaps 【发布时间】:2022-01-12 16:31:46 【问题描述】:我正在使用 Java Spring 和 Oracle DB 创建一个应用程序。
在应用程序中,我想生成一个唯一且有序且没有间隙的主键值:1,2,3,4,5
而不是1,2,5,7,8,9
。
我曾经使用max(id) + 1
来获取id 的最大值,以及下一个/当前事务的id。但是我知道在多个用户或多个会话并发的情况下它并不完美。
我尝试过使用序列,但即使使用ORDER
标签,它仍然可能会造成交易失败的可能性。
REATE SEQUENCE num_seq
START WITH 1
INCREMENT BY 1
ORDER NOCACHE NOCYCLE;
我需要有无间隙值作为要求,但我不确定在多个用户/多个会话的情况下如何实现。
【问题讨论】:
如果删除一行会发生什么?您是否必须重新编号后面的所有行以使值没有间隙?如果插入一行但必须回滚,但同时插入了其他行怎么办? 应用程序正在执行软删除,因此不应从数据库中删除任何记录。 【参考方案1】:别这样。
主键的目的不是显示在 UI 上或暴露给外部世界,而只是提供行的一个唯一标识符。
简单来说,主键不需要性感或好看。这是一个内部标识符。
如果您正在考虑使用序列标识符,这意味着您可能希望将其显示在某个地方,或者您希望将其暴露给外部世界。如果是这种情况,那么创建一个辅助列(也是唯一的)来服务于这个“公共关系”目标。可以自动生成,也可以随意更新,不会影响数据库的完整性。
它也可以由以延迟方式(例如每 10 分钟)运行的辅助进程生成,该进程查找所有“未分配”的新行,并为它们提供新编号。这样做的好处是不易并发并发。
【讨论】:
是的,就是这样。在 Oracle 中是否有特定的方法可以做到这一点?我对 RDMS 还是有点陌生。 @WattMonki 您可以使用 Oracle 调度程序定期运行作业,也可以运行外部 cron 作业。您还可以创建一个接收所有新行的队列和一个从队列中读取并分配新编号的消费者进程。都是不错的人选,大家应该根据自己比较熟悉的来选择。 正如所指出的,“无缝”PK 是徒劳的。即使您尝试在非 PK 列中实现一些“无缝”属性,同样的维护问题仍然适用。除了“这是要求”之外,这个数据元素的真正预期用途是什么,以及它无缝的业务原因是什么? (许多“要求”毫无价值,我们作为分析师的工作就是识别和回击它们)以上是关于有一种方法可以让主键 ID 没有任何间隙的主要内容,如果未能解决你的问题,请参考以下文章