oracle 如何把单行记录拆分为多行

【问题】

表:

xh         kc  
1         语文,数学,英语
2         政治,历史,地理
3         地理,语文
4         地理,数学  

想把上面的表拆分为:

1  语文
1  数学
1  英语
2  政治
2  历史
2  地理
4  地理
4  数学
3  地理
3  语文

按照学号,把课程拆分

【回答】

Oracle 中可以使用层次查询语句结合子查询或随机数完成,这里给出两种写法:

写法 1:

SELECT xh,REGEXP_SUBSTR(kc,'\[^,\]+',1,rn) kc  
FROM t0052,
  (SELECT LEVEL rn 
   FROM DUAL  
   CONNECT BY LEVEL<=(SELECT 
   MAX(length(trim(translate(kc,replace(kc,','),' '))))+1 
   FROM t0052))  
WHERE REGEXP_SUBSTR(kc,'\[^,\]+',1,rn) IS NOT NULL

写法 2:

select xh,regexp_substr(kc,'\[^,\]+',1,level) kc  
from t0052  
connect by level <= (length(kc)-length(regexp_replace(kc,'\[^,\]+','')))  
and rowid= prior rowid  
and prior dbms_random.value is not null;

可以看到上面的两种写法比较复杂,且其中使用了 Oracle 的一些技巧(如为了避免循环错误使用的 prior dbms_random.value is not null),对于使用者有一定难度,而且更换数据库就不能执行了。

这种情况建议使用 SPL 来做,脚本如下:



A

1

$SELECT XH,KC FROM   t0052

2

=A1.news(KC.array();XH,~:KC)


可以看到集算脚本非常简单,其中 A2 即所得结果集:

imagepng

集算器提供 JDBC 接口,可以像数据库一样嵌入到应用程序中,用起来很简单,详细可参考【Java 如何调用 SPL 脚本】。