如何创建单值序列?

How can you create a single-value sequence?

在 prod 环境中,我们在一个字段中有一个巨大的序列(到目前为止,13 位数字)。 在开发环境中,我们要忽略这个序列。 有什么方法可以创建一个始终 returns 相同值的序列?

我的意思是,得到这样的东西:

select my_seq.CURRVAL from dual; --> E.G: 5
select my_seq.NEXTVAL from dual; --> E.G: 5

我试过将增量设置为 0,将 min_value 设置为 max_value,但没有任何效果。 谢谢。

[已编辑]--> Oracle 12c,并且需要始终是相同的值。抱歉,1-2-1-2 序列不符合我们的需求。

不是相同的值,但只有 1 和 2:

SQL> create sequence my_seq START WITH 1 minvalue 1 maxvalue 2 cycle session nocache;

Sequence created.

SQL> select my_seq.nextval from dual connect by level<=5;

   NEXTVAL
----------
         1
         2
         1
         2
         1

注意session 序列需要 Oracle >=12.1

这适用于 10g、11g、12c(没有其他版本可以尝试,但我认为它应该没问题)。

SQL> create sequence my_seq minvalue 0 maxvalue 1 nocache cycle;

Sequence created.

SQL> select my_seq.nextval from dual;

   NEXTVAL
----------
         0

SQL> select my_seq.nextval from dual;

   NEXTVAL
----------
         1

SQL> select my_seq.nextval from dual;

   NEXTVAL
----------
         0

SQL> select my_seq.nextval from dual;

   NEXTVAL
----------
         1

SQL>

不过,正如@a_horse 评论的那样,何必呢?

可以通过对数据字典进行不受支持且具有潜在危险的手动更改来创建 single-value 序列。仅将此解决方案用作最后的手段,切勿 运行 在生产环境中使用,甚至在 运行 将其应用于开发环境之前,在沙箱数据库上对其进行彻底测试,并记录更改,以便未来的开发人员能够理解这是为什么完成。

您不能直接创建所需的序列,因此您必须首先创建一个非常接近的序列 - 初始序列从 5 开始,递增 1,并在 4 和 5 之间循环。在一个有效序列之后已创建,更新 SYS.SEQ$.MINVALUE 以创建一个每次循环回到相同数字的序列。最后,您必须在使用序列之前提交并立即重新启动数据库。 (我不知道为什么,但如果你不重新启动,Oracle 会在你使用序列后立即将 SYS.SEQ$.MINVALUE 改回合法值。)

SYS@orclpdb> create sequence jheller.my_seq start with 5 increment by 1 minvalue 4 maxvalue 5 cycle nocache;

Sequence created.

SYS@orclpdb> update sys.seq$ set minvalue = 5 where obj# = (select object_id from dba_objects where object_name = 'MY_SEQ' and owner = 'JHELLER');

1 row updated.

SYS@orclpdb> commit;

Commit complete.

SYS@orclpdb> shutdown immediate
Pluggable Database closed.
SYS@orclpdb> startup
Pluggable Database opened.
SYS@orclpdb> select jheller.my_seq.nextval from dual;

   NEXTVAL
----------
         5

SYS@orclpdb> select jheller.my_seq.nextval from dual;

   NEXTVAL
----------
         5

以上代码在 19c 上使用多租户选项对我有效。这些序列没有使用任何花哨的新功能,所以我认为代码应该适用于更旧版本的 Oracle。但由于这是不受支持的更改,我无法做出任何承诺。

其他不起作用的想法(但也许他们会激励某人找到更好的解决方案)

您不能直接创建一个根本不递增的序列 - 会生成错误“ORA-04002:INCREMENT 必须是 non-zero 整数”。您也不能创建一个直接循环回最小值的序列,它会生成错误“ORA-04005:INCREMENT 必须小于 MAXVALUE 减去 MINVALUE”。

Overlapping-name 技巧也不管用。虽然使用名为 CURRVAL 和 NEXTVAL 的函数创建名为 MY_SEQ 的包是有效的,但解析器在看到表达式 MY_SEQ.NEXTVAL 时仍将期望一个序列。同样的问题也适用于创建名为 MY_SEQ 的用户,该用户具有 CURRVAL 和 NEXTVAL 的两个函数。