工作和学习中常常会遇到一行要分割成多行数据的情况 ,在此整理一下做下对比。

如果表数据只有一行,则 可以直接在原表上 直接使用 connect by + 正则的方法 , 比如:

select regexp_substr ( '444.555.666' , '[^.]+' , level ) col

from dual

connect level <= regexp_count ( '444.555.666' , '\.' )

输出结果:

如果数据表存在多行数据需要拆分,也可以在原表上使用connect+正则的方法:

with t as

( select '111.222.333' col

from dual

union

select '444.555.666' col

from dual )

select regexp_substr ( col , '[^.]+' , level )

from t

connect level <= regexp_count ( col , '\.\' )

and col = prior col prior dbms_random.value >

---------

使用构造的最大行数值关联原表:

with t as

( select '111.222.333' col

from dual

union

select '444.555.666' col

from dual )

select regexp_substr ( col , '[^.]+' , 1 , lv )

from t , ( select level lv from dual connect level 10 ) b

where b.lv <= regexp_count ( t.col , '\.\' )

这种方法设置第二个数据集的时候要小于可能的最大值,然后两数据集做关联,在做大数据量拆分的时候,这个数值设置得当,拆分行数相对一致的情况下,效率比方法一直接connect by要高。

使用table函数:

with t as

( select '111.222.333' col

from dual

union

select '444.555.666' col

from dual )

select column_value

from t ,

table ( cast ( multiset

( select regexp_substr ( col , '[^.]+' , level ) dd

from dual

connect level <= regexp_count ( t.col , '\.\' )

sys.odcivarchar2list )) a

COLUMN_VALUE

-------------

这个方法输出的列名是固定的,column_value依赖于 sys.odcivarchar2list 这个类型的输出,该方法对于大数据量的拆分效率比第二个方法好。

with t as

( select '111.222.333' col

from dual

union

select '444.555.666' col

from dual )

select regexp_substr ( col , '[^.]+' , trim ( column_value ))

from t ,

xmltable ( concat ( '1 to ' , regexp_count ( t.col , '\.\' ) 1 )) a ;

注意:大数据量的拆分时,谨慎使用正则的方法去做,可以使用substr+instr的方式替换正则。

如果以上方法的效率仍然不理想,可考虑使用plsql块。