4

如何在一个查询中两次选择相同的序列?

我已经用谷歌搜索了这个,但无法得到答案。

为了清楚起见,这就是我需要的,例如:

select seq.nextval as v1, seq.nextval as v2 from dual(我知道这行不通)

我也尝试过 UNION,只是无法理解它。

4

5 回答 5

3

如果您总是需要两个值,您可以将序列更改为以 2 为增量:

alter sequence seq increment by 2;

然后选择当前值及其后继值:

select seq.nextval,
 seq.nextval + 1
 from dual;

不漂亮,但它应该做的工作。

更新

只是为了澄清:ALTER SEQUENCE一生中应该只发布一次,而不是每个会话一次!

于 2013-03-26T13:24:50.690 回答
2

弗兰克的答案有一个缺点:

您不能在事务系统中使用它,因为 ALTER SEQUENCE 提交任何未决的 DML。

肖恩的答案只拉序列一次。据我了解,您想提取两个值。作为 Seans 解决方案的替代方案,您还可以从 .nextval 中选择两次,因为 ORACLE 会两次为您提供相同的值。

我更喜欢将序列包装在一个过程中。这会欺骗 oracle 将序列拉两次。

CREATE or replace FUNCTION GetSeq return number as

nSeq NUMBER;

begin

select seq.nextval into nSeq from dual;

return nSeq;

end;
/

如果你一般需要这个,也许你会喜欢:

CREATE or replace FUNCTION GetSeq(spSeq in VARCHAR2) return number as

nSeq NUMBER;
v_sql long;

begin

v_sql:='select '||upper(spSeq)||'.nextval from dual';
execute immediate v_sql into nSeq;

return nSeq;

end;
/
于 2013-03-26T13:42:20.043 回答
1

如何使用有一些限制NEXTVALOracle 文档中有一个列表。更重要的是,该链接包含一个条件列表,其中 NEXTVAL 将被多次调用。

页面上指定的唯一一个直接 SELECT 将NEXTVAL多次调用的场景是在"A top-level SELECT statement"中。将调用NEXTVAL两次的粗略查询是:

SELECT seq.NEXTVAL FROM (
  SELECT * FROM DUAL
  CONNECT BY LEVEL <= 2) -- Change the "2" to get more sequences

不幸的是,如果您尝试将其推送到子查询中以将值展平为具有列的一行v1并且v2(就像您的问题一样),您将获得ORA-02287: sequence number not allowed here.

这是我能得到的最接近的。如果上面的查询不能帮助您到达您想要的位置,请查看此处发布的其他答案。当我一直在打字时,已经发布了几个很好的答案。

于 2013-03-26T13:51:55.697 回答
1

告诉你多次调用 sequence.nextval 会很无聊,所以你可以尝试以下方法:

create type t_num_tab as table of number;

CREATE SEQUENCE SEQ_TEST
  START WITH 1
  MAXVALUE 999999999999999999999999999
  MINVALUE 1
  NOCYCLE
  CACHE 100
  NOORDER;

create or replace function get_seq_vals(i_num in number) return t_num_tab is 
    seq_tab t_num_tab;
begin

select SEQ_TEST.nextval
bulk collect into seq_tab
from all_objects
where rownum <= i_num;

return seq_tab;

end;

您可以按如下方式使用它。此示例从序列中一次提取 7 个数字:

declare
    numbers t_num_tab;
    idx number;
begin
    -- this grabs x numbers at a time
    numbers := get_seq_vals(7);

    -- this just loops through the returned numbers
    -- to show the values
    idx := numbers.first;
    loop
        dbms_output.put_line(numbers(idx));
        idx := numbers.next(idx);
        exit when idx is null;
    end loop;
end;

另请注意,我使用“next”而不是 first..last,因为您可能希望在迭代之前从列表中删除数字(或者,有时序列缓存可能导致数字增加超过 1)。

于 2013-03-26T14:32:47.893 回答
0

这些都是很好的答案,不幸的是这还不够。以后在挣扎的时候一定能回到这个页面。

我采用了不同的方法。问了一个新问题并得到了我的答案。

你可以去这里看看。

于 2013-03-28T14:17:01.597 回答