web-dev-qa-db-fra.com

Comment puis-je sélectionner une liste de valeurs dans Oracle

Je fais référence à cette réponse stackoverflow:

Comment sélectionner une liste de valeurs dans SQL Server

Comment faire quelque chose de similaire dans Oracle ?

J'ai vu les autres réponses sur cette page qui utilisent UNION et bien que cette méthode fonctionne techniquement, ce n'est pas ce que j'aimerais utiliser dans mon cas.

Je voudrais donc rester avec une syntaxe qui ressemble plus ou moins à une liste de valeurs séparées par des virgules.

[~ # ~] met à jour [~ # ~] en ce qui concerne le create type table _ réponse:

J'ai une table:

CREATE TABLE "BOOK" 
(   "BOOK_ID" NUMBER(38,0)
)

J'utilise ce script mais il n'insère aucune ligne dans la table BOOK:

create type number_tab is table of number;

INSERT INTO BOOK (
    BOOK_ID
)
SELECT A.NOTEBOOK_ID FROM
    (select column_value AS NOTEBOOK_ID from table (number_tab(1,2,3,4,5,6))) A
;

Sortie du script:

TYPE number_tab compiled
Warning: execution completed with warning

Mais si j'utilise ce script, il insère de nouvelles lignes dans la table BOOK:

INSERT INTO BOOK (
    BOOK_ID
)
SELECT A.NOTEBOOK_ID FROM
    (SELECT (LEVEL-1)+1 AS NOTEBOOK_ID FROM DUAL CONNECT BY LEVEL<=6) A
;
44
rapt

Vous n'avez pas besoin de créer de types stockés, vous pouvez évaluer les types de collection intégrés d'Oracle.

select distinct column_value from table(sys.odcinumberlist(1,1,2,3,3,4,4,5))
64
be here now

Si vous souhaitez convertir une liste de valeurs séparée par des virgules:

select column_value 
from table(sys.dbms_debug_vc2coll('One', 'Two', 'Three', 'Four'));

-- Or

select column_value 
from table(sys.dbms_debug_vc2coll(1,2,3,4));

Si vous souhaitez convertir une chaîne de valeurs délimitées par des virgules, je vous recommande la solution SQL d'expression régulière de Justin Cave.

47
Wolf

Il existe différentes manières de prendre une liste séparée par des virgules et de l’analyser sur plusieurs lignes de données. En SQL

SQL> ed
Wrote file afiedt.buf

  1  with x as (
  2    select '1,2,3,a,b,c,d' str from dual
  3  )
  4   select regexp_substr(str,'[^,]+',1,level) element
  5     from x
  6* connect by level <= length(regexp_replace(str,'[^,]+')) + 1
SQL> /

ELEMENT
----------------------------------------------------
1
2
3
a
b
c
d

7 rows selected.

Ou en PL/SQL

SQL> create type str_tbl is table of varchar2(100);
  2  /

Type created.

SQL> create or replace function parse_list( p_list in varchar2 )
  2    return str_tbl
  3    pipelined
  4  is
  5  begin
  6    for x in (select regexp_substr( p_list, '[^,]', 1, level ) element
  7                from dual
  8             connect by level <= length( regexp_replace( p_list, '[^,]+')) + 1)
  9    loop
 10      pipe row( x.element );
 11    end loop
 12    return;
 13  end;
 14
 15  /

Function created.

SQL> select *
  2    from table( parse_list( 'a,b,c,1,2,3,d,e,foo' ));

COLUMN_VALUE
--------------------------------------------------------------------------------
a
b
c
1
2
3
d
e
f

9 rows selected.
5
Justin Cave

Tu peux le faire:

create type number_tab is table of number;

select * from table (number_tab(1,2,3,4,5,6));

La colonne reçoit le nom COLUMN_VALUE de la part d'Oracle, donc cela fonctionne aussi:

select column_value from table (number_tab(1,2,3,4,5,6));
4
Tony Andrews

Salut, il est également possible pour les chaînes avec XML-Table

SELECT trim(COLUMN_VALUE) str FROM xmltable(('"'||REPLACE('a1, b2, a2, c1', ',', '","')||'"'));
3
SkateScout

À partir d'Oracle 12.2, vous n'avez pas besoin de la fonction TABLE, vous pouvez sélectionner directement dans la collection intégrée.

SQL> select * FROM sys.odcinumberlist(5,2,6,3,78);

COLUMN_VALUE
------------
           5
           2
           6
           3
          78

SQL> select * FROM sys.odcivarchar2list('A','B','C','D');

COLUMN_VALUE
------------
A
B
C
D
0
Kaushik Nayak