oracle11g 拆分字符串的详细技巧
2016-07-18 23:26
579 查看
<-->功能需求
有一个比较长的SQL语句,查询出来中间会有类似“abc1,cbd2,db3,db5”这样的行记录,然后想要达到的效果就是将这样的记录按照逗号间隔符拆分出来一条变成4条,这样记录有多条,然后所有有逗号间隔符的都要拆分出来,然后形成新结果集去关联别的表记录。这条长的sql如下:select extractvalue(xmltype(r.approve_content), '/templet/content/nodeId') ids from res_approve_info t inner join res_approve_content r on t.res_approve_info_id=r.res_approve_info_id where t.auth_type_cd='JHGL_KFJH_10' and t.status_cd='2' and t.created_date >to_date('2016-01-01','yyyy-mm-dd') and extractvalue(xmltype(r.approve_content), '/templet/content/isOnTimeOrDelay')='2' |
1、思路分析
核心在于拆分字符串,拆分字符串sql参考先拆分然后再整合成一个临时表,拆分表达式已经想好了大概有如下2种方法:(1) 正则表达式的方式
(2) 存储函数的方式
2、正则表达式的实现方式
必须是oracle 10g+的版本才支持,以逗号间隔:SELECTREGEXP_SUBSTR ('abc1,cbd2,db3,db5', '[^,]+', 1,rownum) FROM DUAL CONNECTBYROWNUM <= LENGTH ('abc1,cbd2,db3,db5') - LENGTH (REPLACE ('abc1,cbd2,db3,db5', ',', ''))+1;
执行如下:
SQL> SQL> SELECT REGEXP_SUBSTR ('abc1,cbd2,db3,db5', '[^,]+', 1,rownum) 2 FROM DUAL 3 CONNECTBYROWNUM <= 4 LENGTH ('abc1,cbd2,db3,db5') - LENGTH (REPLACE ('abc1,cbd2,db3,db5', ',', ''))+1; REGEXP_SUBSTR('ABC1,CBD2,DB3,D ---------------------------------- abc1 cbd2 db3 db5 SQL> |
3、以类型和函数的方式实现
(1)建立TYPE类型CREATEORREPLACETYPE str_split ISTABLEOFVARCHAR2 (4000) |
CREATEORREPLACEFUNCTION fun_splitstr(p_string INVARCHAR2, p_delimiter INVARCHAR2) RETURN str_split PIPELINED AS v_length NUMBER := LENGTH(p_string); v_start NUMBER := 1; v_index NUMBER; BEGIN WHILE(v_start <= v_length) LOOP v_index := INSTR(p_string, p_delimiter, v_start); IF v_index = 0 THEN PIPEROW(SUBSTR(p_string, v_start)); v_start := v_length + 1; ELSE PIPEROW(SUBSTR(p_string, v_start, v_index - v_start)); v_start := v_index + 1; ENDIF; ENDLOOP; RETURN; END fun_splitstr; |
SQL> select * fromtable(select fun_splitstr('abc1,cbd2,db3,db5',',') ids from dual)t1; COLUMN_VALUE -------------------------------------------------------------------------------- abc1 cbd2 db3 db5 SQL> |
4、效率比较高的办法
(1),在java代码(或者存储过程)里面循环遍历如下原始结果集,(2),通过拆分函数,按行循环来拆,把每一个拆出来的结果都插入到一个临时表或者临时集合t3里面,使用select * from table(fun_splitstr('aaa,bbb,ccc',','));来实现。
(3),最后你用这个临时集合去关联你需要关联的表就可以了
select t4.* from t3 left join plan6_node t4where t4.id=t3.id
5、效率比较低的办法(with临时表)
采用with临时表的办法来实现,sql如下,不过效率比较低:with temp0 as (selectLEVEL lv from dual CONNECTBYLEVEL <= 100) selectid,substr(t.vals,instr(t.vals, ',', 1, tv.lv) + 1, instr(t.vals, ',', 1, tv.lv + 1) -( instr(t.vals, ',', 1, tv.lv) + 1) ) ASname from (selectid,',' || name || ','AS vals, length(name || ',') - nvl(length(REPLACE(name, ',')), 0) AS cnt from (select1asid,'abc1,cbd2,db3,db5'asname from dual union allselect2, 'zhangsan1,lisi2,wanger3'from dual) ) t join temp0 tv on tv.lv <= t.cnt orderby1; |
SQL> with temp0 as (selectLEVEL lv from dual CONNECTBYLEVEL <= 100) 2 selectid,substr(t.vals,instr(t.vals, ',', 1, tv.lv) + 1, 3 instr(t.vals, ',', 1, tv.lv + 1) -( 4 instr(t.vals, ',', 1, tv.lv) + 1) 5 ) ASname 6 from (selectid,',' || name || ','AS vals, 7 length(name || ',') - nvl(length(REPLACE(name, ',')), 0) AS cnt 8 from (select1asid,'abc1,cbd2,db3,db5'asname from dual union allselect2, 'zhangsan1,lisi2,wanger3'from dual) 9 ) t join temp0 tv 10 on tv.lv <= t.cnt orderby1; IDNAME ---------- -------------------------------------------------- 1 abc1 1 db3 1 cbd2 1 db5 2 wanger3 2 zhangsan1 2 lisi2 7rows selected SQL> |
临时解决办法是,createtable z_temp2 asselect1asid,'abc1,cbd2,db3,db5'asname from dual union allselect2, 'zhangsan1,lisi2,wanger3'from dual;然后连接这个temp1表进行操作,那么总体sql如下:
createtable z_temp2 asselect1asid,'abc1,cbd2,db3,db5'asname from dual union allselect2, 'zhangsan1,lisi2,wanger3'from dual; with temp0 as (selectLEVEL lv from dual CONNECTBYLEVEL <= 100) selectid,substr(t.vals,instr(t.vals, ',', 1, tv.lv) + 1, instr(t.vals, ',', 1, tv.lv + 1) -( instr(t.vals, ',', 1, tv.lv) + 1) ) ASname from (selectid,',' || name || ','AS vals, length(name || ',') - nvl(length(REPLACE(name, ',')), 0) AS cnt from z_temp2 ) t join temp0 tv on tv.lv <= t.cnt orderby1; |
参考文档:http://www.anbob.com/archives/221.html
相关文章推荐
- Oracle 11g R2 DBA 操作指南(1)
- BestCoder 2nd Anniversary Oracle
- oracle 的绑定变量
- ORA-12560: TNS: 协议适配器错误
- oracle_sql的用法?
- 5.oracle建表的时候同时创建主键,外键,注释,约束,索引
- Oracle SQL性能优化
- oracle rac禁止开机自启动
- HDU-5718 Oracle
- ORACLE和MYSQL查询表字段信息的sql
- BestCoder 2nd Anniversary 1001/hdu5718 Oracle
- oracle数据库如何备份一张表
- HDU 5718 Oracle
- oracle表设计汇总
- Oracle10g_杂
- HDU 5718 Oracle
- Oracle从设计上优化性能汇总
- oracle 高端 必备掌握语句
- 安装Oracle时Enterprise Manager配置失败-实例化EM配置文件出错。
- IMP-00058: ORACLE error 12560 encountered