Joyce,
Éstos son tres ejemplos:
1) Usando dbms_utility.comma_to_table. Esta no es una rutina de propósito general, porque los elementos deben ser identificadores válidos.Con algunos trucos sucios podemos hacer que funcione más universal:
SQL> declare
2 cn_non_occuring_prefix constant varchar2(4) := 'zzzz';
3 mystring varchar2(2000):='a:sd:dfg:31456:dasd: :sdfsdf'; -- just an example
4 l_tablen binary_integer;
5 l_tab dbms_utility.uncl_array;
6 begin
7 dbms_utility.comma_to_table
8 (list => cn_non_occuring_prefix || replace(mystring,':',','||cn_non_occuring_prefix)
9 , tablen => l_tablen
10 , tab => l_tab
11 );
12 for i in 1..l_tablen
13 loop
14 dbms_output.put_line(substr(l_tab(i),1+length(cn_non_occuring_prefix)));
15 end loop;
16 end;
17/
a
sd
dfg
31456
dasd
sdfsdf
PL/SQL-procedure is geslaagd.
2) Usando SQL conecta por nivel. Si usted está en 10g o superior puede usar el método de conexión por nivel en combinación con las expresiones regulares, así:
SQL> declare
2 mystring varchar2(2000):='a:sd:dfg:31456:dasd: :sdfsdf'; -- just an example
3 begin
4 for r in
5 (select regexp_substr(mystring,'[^:]+',1,level) element
6 from dual
7 connect by level <= length(regexp_replace(mystring,'[^:]+')) + 1
8 )
9 loop
10 dbms_output.put_line(r.element);
11 end loop;
12 end;
13/
a
sd
dfg
31456
dasd
sdfsdf
PL/SQL-procedure is geslaagd.
3) usando vez de SQL conectar por nivel, pero ahora en combinación con el bueno de SUBSTR/INSTR en caso de que se encuentran en la versión 9, al igual que usted es:
SQL> declare
2 mystring varchar2(2000):='a:sd:dfg:31456:dasd: :sdfsdf'; -- just an example
3 begin
4 for r in
5 (select substr
6 (str
7 , instr(str,':',1,level) + 1
8 , instr(str,':',1,level+1) - instr(str,':',1,level) - 1
9 ) element
10 from (select ':' || mystring || ':' str from dual)
11 connect by level <= length(str) - length(replace(str,':')) - 1
12 )
13 loop
14 dbms_output.put_line(r.element);
15 end loop;
16 end;
17/
a
sd
dfg
31456
dasd
sdfsdf
PL/SQL-procedure is geslaagd.
se pueden ver algunas más técnicas como éstas, en esta entrada de blog: http://rwijk.blogspot.com/2007/11/interval-based-row-generation.html
Espero que esto ayude.
Saludos, Rob.
Para hacer frente a su comentario:
Un ejemplo de inserción de los valores separados en una tabla normalizada.
En primer lugar crear las tablas:
SQL> create table csv_table (col)
2 as
3 select 'a,sd,dfg,31456,dasd,,sdfsdf' from dual union all
4 select 'a,bb,ccc,dddd' from dual union all
5 select 'zz,yy,' from dual
6/
Table created.
SQL> create table normalized_table (value varchar2(10))
2/
Table created.
porque parece interesado en el enfoque dbms_utility.comma_to_table, menciono aquí. Sin embargo, ciertamente no recomiendo esta variante, debido a las peculiaridades de los identificadores y al lento procesamiento de filas por filas.
SQL> declare
2 cn_non_occuring_prefix constant varchar2(4) := 'zzzz';
3 l_tablen binary_integer;
4 l_tab dbms_utility.uncl_array;
5 begin
6 for r in (select col from csv_table)
7 loop
8 dbms_utility.comma_to_table
9 (list => cn_non_occuring_prefix || replace(r.col,',',','||cn_non_occuring_prefix)
10 , tablen => l_tablen
11 , tab => l_tab
12 );
13 forall i in 1..l_tablen
14 insert into normalized_table (value)
15 values (substr(l_tab(i),length(cn_non_occuring_prefix)+1))
16 ;
17 end loop;
18 end;
19/
PL/SQL procedure successfully completed.
SQL> select * from normalized_table
2/
VALUE
----------
a
sd
dfg
31456
dasd
sdfsdf
a
bb
ccc
dddd
zz
yy
14 rows selected.
Yo no recomendaría este sola variante SQL:
SQL> truncate table normalized_table
2/
Table truncated.
SQL> insert into normalized_table (value)
2 select substr
3 (col
4 , instr(col,',',1,l) + 1
5 , instr(col,',',1,l+1) - instr(col,',',1,l) - 1
6 )
7 from (select ',' || col || ',' col from csv_table)
8 , (select level l from dual connect by level <= 100)
9 where l <= length(col) - length(replace(col,',')) - 1
10/
14 rows created.
SQL> select * from normalized_table
2/
VALUE
----------
a
a
zz
sd
bb
yy
dfg
ccc
31456
dddd
dasd
sdfsdf
14 rows selected.
Saludos, Rob.
Este es un método muy bueno, aún aplicable incluso hasta 11 g como mínimo. Tal método es rápido porque no reinicias tu análisis cada vez desde la posición cero, sino que continúas analizando desde donde lo dejaste. He desarrollado un código que lo maneja un poco diferente, publicado en [mi blog sobre el análisis de una cadena con un CSV en varias columnas] (http://hiflitetm.wordpress.com/2013/11/04/parsing-a-string- with-a-csv-into-multiple-columns /). Es algo similar, pero seguí la ruta con una función segmentada y una forma extraña de usar una combinación cartesiana. Tengo resultados en columnas individuales. – YoYo