1つのクエリで同じシーケンスを2回選択するにはどうすればよいですか?
私はこれをグーグルで検索しましたが、答えを得ることができません。
明確にするために、これは私が必要とするものです、例:
select seq.nextval as v1, seq.nextval as v2 from dual
(私はそれがうまくいかないことを知っています)
UNIONも試してみましたが、頭がおかしくなりません。
常に正確に2つの値が必要な場合は、シーケンスを変更して2ずつインクリメントできます。
alter sequence seq increment by 2;
次に、現在の値とその後継を選択します。
select seq.nextval,
seq.nextval + 1
from dual;
きれいではありませんが、それは仕事をする必要があります。
アップデート
明確にするために:は、ALTER SEQUENCE
セッションごとに1回ではなく、一生に1回だけ発行する必要があります。
フランクによる回答には欠点があります。
ALTER SEQUENCEは保留中のDMLをコミットするため、トランザクションシステムでは使用できません。
Answer of Seanは、シーケンスを1回だけプルします。私が理解しているように、あなたは2つの値を引き出したいと思っています。Seansソリューションの代わりに、.nextvalから2回選択することもできます。これは、ORACLEが同じ値を2回提供するためです。
シーケンスを手順でまとめることをお勧めします。これは、オラクルをだましてシーケンスを2回プルさせます。
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;
/
使用方法にはいくつかの制限がありますNEXTVAL
。Oracleドキュメントにリストがあります。さらに重要なことに、このリンクには、NEXTVALが複数回呼び出される条件のリストが含まれています。
NEXTVAL
ストレートSELECTが複数回呼び出されるページで指定されている唯一のシナリオは、 「トップレベルのSELECTステートメント」にあります。NEXTVAL
2回呼び出す大まかなクエリは次のとおりです。
SELECT seq.NEXTVAL FROM (
SELECT * FROM DUAL
CONNECT BY LEVEL <= 2) -- Change the "2" to get more sequences
残念ながら、これをサブクエリにプッシュして、値を列のある1つの行にフラット化しようとするv1
とv2
(質問のように)、が取得されますORA-02287: sequence number not allowed here
。
これは私が得ることができる限り近いです。上記のクエリで目的の場所を見つけることができない場合は、ここに投稿されている他の回答を確認してください。私がこれを入力している間、いくつかの優れた回答が投稿されました。
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;
また、最初の..lastの代わりに「next」を使用していることにも注意してください。反復する前にリストから番号を削除することをお勧めします(または、シーケンスキャッシュにより、番号が1を超えて増加する場合があります)。
これらはすべて素晴らしい答えですが、残念ながらそれだけでは不十分でした。将来苦労するときは間違いなくこのページに戻ることができます。
私は別の方法で行きました。新しい質問をして、私の答えを得ました。
こちらでチェックしてみてください。