Oracle 序列生成器中的保留编号

Posted

技术标签:

【中文标题】Oracle 序列生成器中的保留编号【英文标题】:Reserve Number in Oracle Sequence Generator 【发布时间】:2021-04-29 21:22:30 【问题描述】:

我们需要在使用 Oracle 序列生成器生成新号码时跳过几个已定义的号码。

例如:- 我们定义的范围为 0001-9999,但在此范围内,Oracle 排序器永远不会生成数字 0011、0020、2056、6547。

可以吗?

【问题讨论】:

序列定义中没有任何内在的东西可以做到这一点。为什么你需要跳过这些?为什么不从你想跳过的最高数字多 1 开始你的序列呢?将序列限制在仅 9999 的范围内有缺陷的设计或对如何最好地使用序列的理解有缺陷。当你的 seq.达到9999?您如何使用这些数字? 我可以理解为什么有人想要保留一些数字,例如,为了测试的目的。我会通过从 10000 开始我的序列来简化它,而不用担心只有 4 个特殊数字。 【参考方案1】:

可以吗?

有点……只要在 2057 开始序列并在 6546 停止它,那么您将永远不会生成任何这些值。

如果您想从 1 开始到 9999 跳过这些值,那么,不,Oracle 序列中没有任何内容允许您这样做。

【讨论】:

【参考方案2】:

您不能仅在内置序列机制中做到这一点。作为一种解决方法,您可以有一个跳过禁止值的包装函数,例如:

CREATE FUNCTION get_seq RETURN NUMBER IS
  seq_val PLS_INTEGER := 11; -- any banned value
BEGIN
  WHILE seq_val IN (11, 20, 2056, 6547) LOOP
    seq_val := my_seq.nextval;
  END LOOP;
  RETURN seq_val;
END;
/

然后调用get_seq 代替my_seq.nextval

db<>fiddle demp 具有较小的范围,表明它跳过了值。

当然也有缺点;您可能会看到上下文切换对性能的显着影响,尽管范围如此之小,您可能不会非常强烈地调用它。如果您的禁用号码发生变化,您必须更改函数,或者让函数从其他地方查找它们 - 例如,如果您要避免现有的 PK 值,您可能需要或想要这样做。必须引用不同的东西来检索nextval(间接通过函数)和currval(直接来自序列)可能会令人困惑。等等。但这是一种选择……

如果您要避免现有的 PK 值,那么另一种选择是坚持一个简单的序列并插入一个循环,当您没有遇到约束错误时退出 - 即通常在一次迭代之后。但目前尚不清楚您真正想要实现的目标。

【讨论】:

以上是关于Oracle 序列生成器中的保留编号的主要内容,如果未能解决你的问题,请参考以下文章

Oracle序列生成器

使用从序列对象生成的数据库 ID 创建 Oracle 视图

Oracle数据库导入Excel铺底数据 -含自动插入生成自定义序列号

Oracle数据库导入Excel铺底数据 -含自动插入生成自定义序列号

序列的作用

Oracle中的序列(Sequence)