バインド変数(たとえば:NUM)を受け入れるSQLクエリを作成し、その出力は1つの列と:NUMの行数で構成され、各行には行番号があります。つまり、:NUMを7として渡すと、出力は次のようになります。
VAL
====
1
2
3
4
5
6
7
クエリに実際のDBテーブルを含めたり、PL/SQLコードを使用したりしないでください。つまり、クエリではデュアルのみを使用する必要があります
これを達成する方法はありますか?
あなたが使用することができます:
WHERE ROWNUM <= :NUM
...ただし、テーブルには、バインド変数の制限以上の行が含まれている必要があります。 このリンクは、Oracleでのさまざまな行番号生成手法を示しています 。
CONNECT BY
を使用して、Oracle 10g +:
SELECT LEVEL
FROM DUAL
CONNECT BY LEVEL <= :NUM
バインド変数を使用できることをmonojohnny
で確認しました。 CONNECT BY
構文はサポートされていますが、Oracle 9iで実行しようとすると、ORA-01436エラーが発生します。
私が100%ではない唯一のことは、CONNECTBYがバインド変数からの制限を受け入れるかどうかです。
参照:
次のようなものを試してください:
SELECT 1 AS Val FROM dual
UNION ALL SELECT 2 FROM dual
UNION ALL SELECT 3 FROM dual
UNION ALL SELECT 4 FROM dual
UNION ALL SELECT 5 FROM dual
UNION ALL SELECT 6 FROM dual
UNION ALL SELECT 7 FROM dual;
それは厄介ですが、それはトリックを行います。
編集:ああ-どのくらいの高さになるかを知らせるために変数を渡す必要があります...
では、次のようなものはどうですか?
SELECT t1.Val + t2.Val * 2 + t3.Val * 4 + t4.Val * 8 AS Val
FROM
(
SELECT 0 AS Val FROM dual
UNION ALL SELECT 1 FROM dual
) AS t1,
(
SELECT 0 AS Val FROM dual
UNION ALL SELECT 1 FROM dual
) AS t2,
(
SELECT 0 AS Val FROM dual
UNION ALL SELECT 1 FROM dual
) AS t3,
(
SELECT 0 AS Val FROM dual
UNION ALL SELECT 1 FROM dual
) AS t4
WHERE t1.Val + t2.Val * 2 + t3.Val * 4 + t4.Val * 8 <= 7;
わかりました...もう一度編集します。WITHを使用します。
WiTH
A0 AS (SELECT 0 as N FROM DUAL UNION ALL SELECT 0 FROM DUAL),
A1 AS (SELECT 0 as N FROM A0, A0 AS B),
A2 AS (SELECT 0 as N FROM A1, A1 AS B),
A3 AS (SELECT 0 as N FROM A2, A2 AS B),
A4 AS (SELECT 0 as N FROM A3, A3 AS B),
A5 AS (SELECT 0 as N FROM A4, A4 AS B),
A6 AS (SELECT 0 as N FROM A5, A5 AS B),
Nums AS (SELECT ROW_NUMBER() OVER (ORDER BY N) AS Val FROM A6)
SELECT *
FROM Nums
WHERE Val <= :NUM
;
私はこの答えを思いつきませんでした[投票が正しい方向に進むことを確認してください!!]、それは上記の「OMGPonies」[メソッドがバインディング変数で機能するかどうかわからなかった]に基づく私のテストノートです参考のために:
Connected to:
Oracle Database 10g Enterprise Edition Release 10.2.0.1.0 - Production
With the Partitioning, OLAP and Data Mining options
SQL> var num_rows number
SQL> begin select 20 into :num_rows from dual;
2 end;
3 /
PL/SQL procedure successfully completed.
SQL> select level from dual
2 connect by level <=:num_rows;
LEVEL
----------
1
2
3
4
...
接続せずにクエリ
WITH num(n) as(select 1 from dual union all
select n+1 from num where n <= :num_limit)
select * from num
このコミュニティウィキは、テーブルがないという要件に実際には答えていないため、マークを付けていますが、データベースをインストールするときに最初に行うことの1つは、この種の目的でテーブルのセットを作成することです。
これを行うことにより、(最小限で安価な)ディスク容量を犠牲にして、多数のクエリの複雑さを大幅に軽減し、速度を向上させます。
あなたはそれについて真剣に考えるべきです。日付テーブルを維持することを除けば、必要な維持管理はそれほど多くありません。
別の方法は、XQuery範囲式を使用することです。例:
select column_value from xmltable(:a||' to '||:b);
1
2
3
4
5
6
7
8
9
10
このソリューションは非常に柔軟性があります。例:
select column_value from xmltable('5 to 10, 15 to 20');
5
6
7
8
9
10
15
16
17
18
19
20
別の解決策では、行を含むコレクションを返す関数を作成するためにPL/SQLが必要になります..._select level from dual connect by level <= :b1
_アプローチほど単純ではありませんが、いくつかの状況で役立ちます。
1)数値テーブルオブジェクトタイプ(この例ではnumber_tbl)を作成します。
_create or replace type number_tbl as table of number;
_
2)生成される行数を受け取る関数を作成し、結果とともにnumber_tblオブジェクトを返します。
_create or replace function get_rows( i_num_rows number ) return number_tbl as
t number_tbl := number_tbl();
begin
if i_num_rows < 1 then
return null;
end if;
t.extend( i_num_rows );
for i in 1..i_num_rows loop
t(i) := i;
end loop;
return t;
end get_rows;
_
3)table( ... )
関数を使用して関数から選択し、number_tblオブジェクトを選択可能なものに変換します。
_select * from table( cast ( get_rows( :b1 ) as number_tbl ) );
_
WITH cte_numbers(n)
AS (
SELECT 0
UNION ALL
SELECT n + 1
FROM cte_numbers
WHERE n < 10
)
SELECT n
FROM cte_numbers;
返された行01 2 3 4 5 6 7 8 9 10
接続するのはとても素晴らしいことです。デュアルテーブルで利用可能な単一のデータセットで複数の行を生成するのに役立ちます。これは、ダミーデータの膨大な数の行を生成するのに役立ちます。例えば
insert into test select a.* from test1 a,(select * from dual connect by level <=100000) b;
またはあなたはこのようなことをすることができます
例2:1から10までの数の平方と立方体を印刷したいとします。
SQL> select level "No", power(level,2) "Square", power(level,3) "Cube" from dual connect by level <= 10;
No Square Cube
---------- ---------- ----------
1 1 1
2 4 8
3 9 27
4 16 64
5 25 125
6 36 216
7 49 343
8 64 512
9 81 729
10 100 1000
したがって、好きな形で操作できます。これは、デュアルテーブルから複数の行を返す方法です。参照: http://www.oraclebin.com/2012/12/multipe-rows-from-dual-table.html