在 PL/SQL 语句中两次使用相同的序列

Mic*_*l-O 7 oracle plsql sequence

我今天写了 PL/SQL 的片段:

declare
  first_id number;
  second_id number;
begin
  insert into table (sort_nr, text_id, unit_id) values(...,
  table_seq.nextval, table_seq.nextval) returning text_id, unit_id 
  into first_id, second_id;
  dbms_output.put_line(first_id);
  dbms_output.put_line(second_id);
end;
Run Code Online (Sandbox Code Playgroud)

并收到了唯一的常量违规。经过进一步检查,我发现了它,first_id并且second_id在其中具有相同的价值。

我的问题是:在同一个语句中多次调用同一个序列并接收后续号码是否有任何限制?从我的角度来看,似乎nextval只在查询范围内调用一次并缓存。

只是附带说明,我无法更改那个糟糕的架构以避免在两列中使用相同的序列。

Vin*_*rat 9

这是预期的行为nextval文件

在包含对 NEXTVAL 的引用的单个 SQL 语句中,Oracle 将序列递增一次:

  • 对于 SELECT 语句的外部查询块返回的每一行

[...] 如果这些位置中的任何一个包含多个对 NEXTVAL 的引用,则 Oracle 将序列递增一次,并为所有出现的 NEXTVAL 返回相同的值。

这意味着您将无法使用普通 SQL 来克服此限制:您将需要一些 PL/SQL。填充两个字段的触发器或包装序列调用的函数。这是一个带有 11g 的函数的示例:

SQL> create sequence table_seq;

Sequence created.

SQL> create table test (sort_nr number, text_id number, unit_id number);

Table created.

SQL> create or replace function getid return number is begin return table_seq.nextval; end;
  2  /

Function created.

SQL> insert into test values (1, getid, getid);

1 row created.

SQL> select * from test;

   SORT_NR    TEXT_ID    UNIT_ID
---------- ---------- ----------
         1          1          2
Run Code Online (Sandbox Code Playgroud)