web-dev-qa-db-fra.com

Requête SQL pour retourner N lignes de dual

Je veux écrire une requête SQL qui accepte une variable de liaison (disons: NUM) et dont le résultat consiste en une colonne &: NUM nombre de lignes, chaque ligne ayant son numéro. c'est-à-dire si nous passons: NUM à 7, le résultat devrait être:

VAL
====
1
2
3
4
5
6
7

Aucune requête de base de données ne doit exister dans la requête et aucun code PL/SQL ne doit être utilisé. c'est-à-dire que seul le double doit être utilisé dans la requête

Y'a-t-il une quelconque façon de réussir cela?

14
Harish

Vous pouvez utiliser:

 WHERE ROWNUM <= :NUM

... mais la table doit contenir une ligne égale ou supérieure à la limite dans la variable bind. Ce lien présente diverses techniques de génération de numéros de ligne dans Oracle .

En utilisant CONNECT BY, Oracle 10g +:

SELECT LEVEL
  FROM DUAL
CONNECT BY LEVEL <= :NUM

Confirmé par monojohnny que la variable bind peut être utilisée. Les tentatives d'exécution sur Oracle 9i, bien que la syntaxe CONNECT BY soit prise en charge, entraînent une erreur ORA-01436.

La seule chose sur laquelle je ne suis pas à 100%, c'est si le CONNECT BY acceptera la limite de la variable bind.

Référence:

34
OMG Ponies

Essayez quelque chose comme:

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;

C'est désordonné, mais ça fera l'affaire.

Édité: Ah - vous devez passer une variable pour vous dire à quelle hauteur aller ...

Alors que diriez-vous de quelque chose comme:

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;

Ok ... retouche encore, maintenant avec 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
;
4
Rob Farley

Je n'ai pas trouvé cette réponse [assurez-vous que tous les votes vont dans le bon sens !!], c'est juste mes notes de test basées sur 'OMG Ponies' [qui ne savait pas si la méthode fonctionnerait avec une variable de liaison] ci-dessus pour référence:

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
 ...
3
monojohnny

Requête sans se connecter par

WITH num(n) as(select 1 from dual union all
select n+1 from num where n <= :num_limit)
select * from num
2
lunicon

Je marque ce wiki de communauté car il ne répond pas à votre exigence de ne pas avoir de table, mais l'une des premières choses que nous faisons lorsque nous installons une base de données consiste à créer un ensemble de tables à cette fin.

  • Une table contenant un grand nombre d'entiers (par exemple, -99999 à 99999).
  • Un tableau contenant chaque date de 10 ans dans le passé à 10 ans dans le futur (qui est continuellement ajouté à chaque mois et coupé occasionnellement).
  • Un tableau contenant chaque heure de la journée.

Ce faisant, nous réduisons considérablement la complexité et augmentons la rapidité d'un grand nombre de requêtes, au détriment de l'espace disque (minimal et économique).

Vous devriez réfléchir sérieusement à cela. Mis à part le maintien de la table de date, il ne nécessite pas beaucoup d’entretien.

0
paxdiablo

Une autre méthode consiste à utiliser une expression de plage XQuery, par exemple:

select column_value from xmltable(:a||' to '||:b);

 1
 2
 3
 4
 5
 6
 7
 8
 9
10

Cette solution est assez flexible, par exemple:

select column_value from xmltable('5 to 10, 15 to 20');

 5
 6
 7
 8
 9
10
15
16
17
18
19
20
0
Jeffrey Kemp

Une autre solution nécessiterait un peu de PL/SQL pour créer une fonction permettant de renvoyer une collection avec les lignes ... Pas aussi simple que l'approche select level from dual connect by level <= :b1, mais elle est utile dans quelques situations:

1) Créez un type d'objet de table numérique (number_tbl, dans cet exemple):

create or replace type number_tbl as table of number;

2) Créez une fonction qui recevra le nombre de lignes à générer, puis renvoyez un objet number_tbl avec les résultats:

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) sélectionnez votre fonction en utilisant la fonction table( ... ) pour transformer votre objet number_tbl en quelque chose de sélectionnable:

select * from table( cast ( get_rows( :b1 ) as number_tbl ) );
0
R. Genaro

se connecter par est une telle chose merveilleuse. Il vous aide à générer plusieurs lignes avec un seul ensemble de données disponibles dans une table double. Cela peut vous aider à générer un très grand nombre de lignes pour vos données factices. Par exemple

insert into test select a.* from test1 a,(select * from dual connect by level <=100000) b;

ou tu peux faire quelque chose comme ça

Exemple 2: vous souhaitez imprimer un carré et un cube de nombres de 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

Vous pouvez donc le manipuler sous la forme de votre choix. Voici comment vous pouvez renvoyer plusieurs lignes de la double table. Références: http://www.oraclebin.com/2012/12/multipe-rows-from-dual-table.html

0
Sushant Butta