2012-04-27 10 views
34

Me refiero a esta stackoverflow respuesta:¿Cómo puedo seleccionar de la lista de valores en Oracle

How can I select from list of values in SQL Server

¿Cómo puede algo similar hacerse en Oracle?

He visto las otras respuestas en esta página que usan UNION y aunque este método funciona técnicamente, no es lo que me gustaría usar en mi caso.

Así que me gustaría quedarme con la sintaxis que más o menos parece una lista de valores separados por comas.

ACTUALIZACIÓNcon respecto a la create type tableanswer:

Tengo una tabla:

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

utilizo este guión, pero no se inserta ninguna fila de la tabla 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 
; 

Resultado del script:

TYPE number_tab compiled 
Warning: execution completed with warning 

Pero si uso este script lo hace insertar nuevas filas a la tabla 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 
; 

Respuesta

47

No necesita crear ningún tipo almacenado, puede evaluar los tipos de colección incorporados de Oracle.

select distinct column_value from table(sys.odcinumberlist(1,1,2,3,3,4,4,5)) 
+0

¡Funciona ...! y es lo que estaba buscando. Si puede averiguar por qué la respuesta de Tony Andrews (http://stackoverflow.com/questions/10353969/how-can-i-select-from-list-of-values-in-oracle/10354083#10354083) me la está dando una advertencia y no produce inserciones, por favor avíseme. – rapt

+0

gracias! trabajado para mí en orcl 11g. No puedo evitar preguntarme ¿cómo se les ocurrieron estos nombres? odcinumberlist vs dbms_debug_vc2coll nada de esto parece pensado en absoluto –

+1

@SonicSoul porque ninguno de ellos estaba destinado para el uso "casual" como en mi respuesta anterior. ODCI significa interfaz de cartucho de datos Oracle, dbms_debug_vc2_coll está destinado a ser utilizado con el paquete DBMS_DEBUG. –

3

usted puede hacer esto:

create type number_tab is table of number; 

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

La columna se le da el nombre column_value por Oracle, así que esto también funciona:

select column_value from table (number_tab(1,2,3,4,5,6)); 
+0

Parece que debería funcionar .. pero me estoy haciendo: 'number_tab TIPO compilado. Advertencia: ejecución completada con warning', y donde uso este código (dentro de un encapsulado 'INSERT'), el encapsulado' INSERT' no funciona. P.ej.Yo 'INSERT INTO libro ( BOOK_ID ) SELECT A.NOTEBOOK_ID DE (seleccione column_value AS NOTEBOOK_ID de la tabla (number_tab (1,2,3,4,5,6))) Un ;' - ninguna fila era insertado ... ¿qué estoy haciendo mal? – rapt

+0

No sé qué estás haciendo mal, o qué está mal: también estoy en 11G y funciona de mí. ¿Cuál es la advertencia que está consiguiendo al crear el tipo? No recibo ninguna advertencia. –

+0

, consulte la actualización anterior. – rapt

5

Existen varias formas de tomar una lista separada por comas y analizarla en varias filas de datos. 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. 

O 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. 
+0

En mi experiencia, siempre he usado la misma lógica de la pregunta. ¿Por qué las formas que describió para lograr ese resultado deberían preferirse al uso de colecciones? ¡Especialmente el que usa expresiones regulares y consultas jerárquicas parece muy complejo de evaluar! Gracias –

+0

@Justin Cave: ¡Gracias, fue brillante! – rapt

33

Si usted está tratando de convertir una lista separada por comas de los valores:

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 desea convertir una cadena de coma valores delimitados, entonces recomendaría la solución SQL de expresión regular de Justin Cave.

+0

Agradable. ¡Ni siquiera tuve que conceder permisos para ese procedimiento! – Sebas

0

Hola, también es posible para cuerdas con XML-Tabla

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