Oracle数据行拆分多行

时间:2021-11-11 10:27:50

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

单行拆分

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

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

from dual

connectbylevel<= regexp_count('444.555.666','\.')+1

输出结果:

COL

----

444

555

666

 

多行拆分

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

方法一

with t as

(select'111.222.333' col

from dual

unionall

select'444.555.666' col

from dual)

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

from t

connectbylevel<= regexp_count(col,'\.\')+1

and col =prior col

andprior dbms_random.value >0

结果:

---------

111

222

333

444

555

666

 

方法二

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

with t as

(select'111.222.333' col

from dual

unionall

select'444.555.666' col

from dual)

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

from t,(selectlevel lv from dual connectbylevel<10) b

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

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

方法三

使用table函数:

with t as

(select'111.222.333' col

from dual

unionall

select'444.555.666' col

from dual)

selectcolumn_value

from t,

table(cast(multiset

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

from dual

connectbylevel<= regexp_count(t.col,'\.\')+1)as

sys.odcivarchar2list)) a

结果:

COLUMN_VALUE

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

111

222

333

444

555

666

 

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

方法四

 

with t as

(select'111.222.333' col

from dual

unionall

select'444.555.666' col

from dual)

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

from t,

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

 

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

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