测试数据:
CREATE TABLE t (str VARCHAR2(30)); INSERT INTO t VALUES ( 'X,Y,Z' ); INSERT INTO t VALUES ( 'XXX,Y,ZZ,AAAAA,B,CCC,D,E,F,GGG' ); commit;
SQL> CREATE OR REPLACE TYPE number_ntt AS TABLE OF NUMBER; 2 / Type created SQL> col value for a20 SQL> SQL> with ilv as 2 (select str || ',' as str, 3 (length(str) - length(replace(str, ','))) + 1 as no_of_elements 4 from t) 5 select a.str, regexp_substr(a.str, '[^,]+', 1, b.column_value) value 6 from ilv a, table(cast(multiset (select rownum rn 7 from dual 8 connect by rownum <= a.no_of_elements) as number_ntt)) b; STR VALUE ------------------------------- -------------------- X,Y,Z, X X,Y,Z, Y X,Y,Z, Z XXX,Y,ZZ,AAAAA,B,CCC,D,E,F,GGG, XXX XXX,Y,ZZ,AAAAA,B,CCC,D,E,F,GGG, Y XXX,Y,ZZ,AAAAA,B,CCC,D,E,F,GGG, ZZ XXX,Y,ZZ,AAAAA,B,CCC,D,E,F,GGG, AAAAA XXX,Y,ZZ,AAAAA,B,CCC,D,E,F,GGG, B XXX,Y,ZZ,AAAAA,B,CCC,D,E,F,GGG, CCC XXX,Y,ZZ,AAAAA,B,CCC,D,E,F,GGG, D XXX,Y,ZZ,AAAAA,B,CCC,D,E,F,GGG, E XXX,Y,ZZ,AAAAA,B,CCC,D,E,F,GGG, F XXX,Y,ZZ,AAAAA,B,CCC,D,E,F,GGG, GGG 13 rows selected SQL>
SQL> select str, 2 regexp_substr(str, '[^,]+', 1, level) value 3 from t 4 connect by 5 str = prior str 6 and instr(str||',', ',', 1, level) > 0 7 and prior dbms_random.value is not null; STR VALUE ------------------------------ -------------------- X,Y,Z X X,Y,Z Y X,Y,Z Z XXX,Y,ZZ,AAAAA,B,CCC,D,E,F,GGG XXX XXX,Y,ZZ,AAAAA,B,CCC,D,E,F,GGG Y XXX,Y,ZZ,AAAAA,B,CCC,D,E,F,GGG ZZ XXX,Y,ZZ,AAAAA,B,CCC,D,E,F,GGG AAAAA XXX,Y,ZZ,AAAAA,B,CCC,D,E,F,GGG B XXX,Y,ZZ,AAAAA,B,CCC,D,E,F,GGG CCC XXX,Y,ZZ,AAAAA,B,CCC,D,E,F,GGG D XXX,Y,ZZ,AAAAA,B,CCC,D,E,F,GGG E XXX,Y,ZZ,AAAAA,B,CCC,D,E,F,GGG F XXX,Y,ZZ,AAAAA,B,CCC,D,E,F,GGG GGG 13 rows selected SQL>
SQL> with tmp as ( 2 select t.*, 3 length(str)-length(regexp_replace(str, ',', ''))+1 len 4 from t 5 ) 6 select a.*, regexp_substr(str, '[^,]+', 1, rn) value 7 from tmp a, (select rownum rn from dual connect by level <= (select max(len) from tmp x)) b 8 where a.len>=b.rn 9 order by 1; STR LEN VALUE ------------------------------ ---------- -------------------- X,Y,Z 3 Y X,Y,Z 3 Z X,Y,Z 3 X XXX,Y,ZZ,AAAAA,B,CCC,D,E,F,GGG 10 GGG XXX,Y,ZZ,AAAAA,B,CCC,D,E,F,GGG 10 B XXX,Y,ZZ,AAAAA,B,CCC,D,E,F,GGG 10 CCC XXX,Y,ZZ,AAAAA,B,CCC,D,E,F,GGG 10 D XXX,Y,ZZ,AAAAA,B,CCC,D,E,F,GGG 10 E XXX,Y,ZZ,AAAAA,B,CCC,D,E,F,GGG 10 F XXX,Y,ZZ,AAAAA,B,CCC,D,E,F,GGG 10 ZZ XXX,Y,ZZ,AAAAA,B,CCC,D,E,F,GGG 10 Y XXX,Y,ZZ,AAAAA,B,CCC,D,E,F,GGG 10 XXX XXX,Y,ZZ,AAAAA,B,CCC,D,E,F,GGG 10 AAAAA 13 rows selected SQL>
SQL> col single_element for a15 SQL> SQL> with ilv as 2 (select str as orig_str, 3 ',' || str || ',' as mod_str, 4 1 as start_pos, 5 length(str) as end_pos, 6 (length(str) - length(replace(str, ','))) + 1 as element_count, 7 0 as element_no, 8 rownum as rn 9 from t) 10 select orig_str as original_string, 11 substr(mod_str, start_pos, end_pos - start_pos) as single_element, 12 element_no, 13 element_count 14 from (select * 15 from ilv 16 model partition by(rn, orig_str, mod_str) 17 dimension by(element_no) 18 measures(start_pos, end_pos, element_count) 19 rules iterate(2000) 20 until(iteration_number + 1 = element_count[0])( 21 start_pos[iteration_number + 1] = instr(cv(mod_str), ',', 1, cv(element_no)) + 1, 22 end_pos[iteration_number + 1] = instr(cv(mod_str), ',', 1, cv(element_no) + 1) 23 ) 24 ) 25 where element_no != 0 26 order by mod_str, element_no; ORIGINAL_STRING SINGLE_ELEMENT ELEMENT_NO ELEMENT_COUNT ------------------------------ --------------- ---------- ------------- X,Y,Z X 1 X,Y,Z Y 2 X,Y,Z Z 3 XXX,Y,ZZ,AAAAA,B,CCC,D,E,F,GGG XXX 1 XXX,Y,ZZ,AAAAA,B,CCC,D,E,F,GGG Y 2 XXX,Y,ZZ,AAAAA,B,CCC,D,E,F,GGG ZZ 3 XXX,Y,ZZ,AAAAA,B,CCC,D,E,F,GGG AAAAA 4 XXX,Y,ZZ,AAAAA,B,CCC,D,E,F,GGG B 5 XXX,Y,ZZ,AAAAA,B,CCC,D,E,F,GGG CCC 6 XXX,Y,ZZ,AAAAA,B,CCC,D,E,F,GGG D 7 XXX,Y,ZZ,AAAAA,B,CCC,D,E,F,GGG E 8 XXX,Y,ZZ,AAAAA,B,CCC,D,E,F,GGG F 9 XXX,Y,ZZ,AAAAA,B,CCC,D,E,F,GGG GGG 10 13 rows selected SQL>