Joyce,
Ecco tre esempi:
1) Utilizzo di dbms_utility.comma_to_table. Questa non è una routine generica, perché gli elementi dovrebbero essere identificativi validi.Con alcuni trucchetti sporchi possiamo farlo funzionare in modo più universale:
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) Utilizzo del collegamento SQL per livello. Se siete su 10g o superiore è possibile utilizzare il metodo connect-by-livello in combinazione con le espressioni regolari, come questo:
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) Anche in questo caso utilizzando di SQL collegare per livello, ma ora in combinazione con il buon vecchio SUBSTR/INSTR nel caso in cui si è sulla versione 9, come siete:
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.
si possono vedere alcune più tecniche come questi, in questo blogpost: http://rwijk.blogspot.com/2007/11/interval-based-row-generation.html
Spero che questo aiuti.
Cordiali saluti, Rob.
Per affrontare un commento:
Un esempio inserendo i valori separati in una tabella normalizzata.
Innanzitutto creare le tabelle:
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.
Perché lei sembra interessato al metodo dbms_utility.comma_to_table, ho citato qui. Tuttavia, non raccomando questa variante, a causa delle stranezze dell'identificatore e a causa dell'elaborazione lenta riga dopo riga.
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.
Vi consiglio questo sola variante di 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.
saluti, Rob.
Questo è un ottimo metodo, applicabile anche fino a 11g almeno. Tale metodo è veloce perché non si riavvia l'analisi ogni volta dalla posizione zero, ma continua l'analisi da dove si era interrotto. Ho sviluppato un codice un po 'diverso, pubblicato su [il mio blog su Parsing di una stringa con un CSV in più colonne] (http://hiflitetm.wordpress.com/2013/11/04/parsing-a-string- con-un-csv-in-più-colonne /). È un po 'simile, ma ho seguito il percorso con una funzione pipeline e un modo strano di usare un join cartesiano. Ho dei risultati in singole colonne. – YoYo