Я хочу записать SQL-запрос, который принимает связывать переменную (скажите: ЦИФРА), и ее вывод состоит из одного столбца и: ЦИФРОВОЕ количество строк, каждой строки, имеющей ее номер строки. т.е. если мы передаем: ЦИФРА как 7, вывод должен быть:
VAL
====
1
2
3
4
5
6
7
Не должно быть никаких фактических Таблиц базы данных в запросе, и никакой МН / код SQL не должен использоваться. т.е. только двойной должен использоваться в запросе
Там какой-либо путь состоит в том, чтобы достигнуть этого?
можно было бы использовать:
WHERE ROWNUM <= :NUM
... но таблица должна содержать строку, равную или большую до предела в переменной bind. Эта ссылка демонстрирует различные методы генерации номеров строк в Oracle.
Используя CONNECT BY
, Oracle 10g+:
SELECT LEVEL
FROM DUAL
CONNECT BY LEVEL <= :NUM
подтверждает monojohnny
, что переменная привязки может быть использована. Попытки запускать Oracle 9i, хотя синтаксис CONNECT BY
поддерживается, приводят к ошибке ORA-01436.
Единственное, на чем я не уверен на 100%, это если CONNECT BY примет лимит от переменной bind.
Ссылка:
Попробуй что-нибудь вроде:
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
;
Я не придумал этот ответ [ так что убедитесь, что все голоса идут в правильном направлении!!!] ] , это просто мои тестовые заметки, основанные на 'OMG Ponies' [который не был уверен, будет ли метод работать с переменной связывания] выше для справки:
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
...
Я помечаю эту вики-сообщество, так как на самом деле она не отвечает вашим требованиям по отсутствию таблиц, но одно из первых, что мы делаем при установке базы данных - это создаём набор таблиц для такого рода целей.
Тем самым мы значительно уменьшаем сложность и увеличиваем скорость большого количества наших запросов за счет (минимального и дешевого) дискового пространства.
Вы должны серьезно подумать об этом. Помимо ведения таблицы дат, в обслуживании не так уж и много нужно.
.В зависимости от базы данных можно использовать различные методы.
PostgreSQL имеет хорошую возможность -- series.
Получить то, что вы хотите, можно просто:
SELECT * FROM generate_series(1, NUM);
Другое решение потребует некоторого PL/SQL для создания функции возврата коллекции со строками... Не так просто, как подход уровня select из двойного соединения по уровню <= :b1
, но это полезно в нескольких ситуациях:
1) Создать тип объекта number table ( 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) select из вашей функции с помощью функции table( . ... )
для превращения вашего объекта number_tbl в нечто выбираемое:
select * from table( cast ( get_rows( :b1 ) as number_tbl ) );