转自:http://m.blog.csdn.net/article/details?id=51946573

<-->功能需求

                有一个比较长的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)

(2)建立FUNCTION存储函数

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;

(3)      开始验证使用函数

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>

这里效率比较低的原因是:select1asid,'abc1,cbd2,db3,db5'asname  from dual union  allselect2, 'zhangsan1,lisi2,wanger3'from dual,这里临时表,以为需要大量不停的循环遍历它,如果表数据量大或者获取比较复杂的话,这里就会卡死的。

临时解决办法是,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;

这样用临时表的缺陷就是,不能一条sql搞定,需要分2个阶段来执行,而且每次都需要清空临时表z_temp2,这点比较麻烦。

参考文档:http://www.anbob.com/archives/221.html

oracle11g 拆分字符串的详细技巧的更多相关文章

  1. T-SQL技巧收集——拆分字符串

    原文:T-SQL技巧收集--拆分字符串 在开发中,很多时候都需要处理拆分字符串的操作.下面收集了几种方法供大家分享,其中的逗号可以改为多种有需要的符号,但是不能针对多种符号同时存在的例子.有待各位补充 ...

  2. Scripting.FileSystemObject对象的详细技巧指南

    Scripting.FileSystemObject对象的详细技巧指南 FileSystemObject对象提供对计算机文件系统的访问: powered by 25175.net 在代码内操作文本文件 ...

  3. OMG,12 个精致的 Java 字符串操作小技巧,学它

    字符串可以说是 Java 中最具有代表性的类了,似乎没有之一哈,这就好像直播界的李佳琪,脱口秀中的李诞,一等一的大哥地位.不得不承认,最近吐槽大会刷多了,脑子里全是那些段子,写文章都有点不由自主,真的 ...

  4. R语言拆分字符串

    R语言拆分字符串 aaa<-"aa;bb;cc"ccc<-strsplit(aaa,split=";") bbb<- unlist(strsp ...

  5. 【SQL】sql版Split函数。用于拆分字符串为单列表格

    功能与.net版string.Split函数类似,只不过.net返回的是数组,这个返回的是一个单列表格,每个拆分出来的子串占一行.可选是否移除空格子串和重复项.市面上类似的函数不算少,但大多都是在循环 ...

  6. python split()函数使用拆分字符串 将字符串转化为列表

    函数:split()Python中有split()和os.path.split()两个函数,具体作用如下:split():拆分字符串.通过指定分隔符对字符串进行切片,并返回分割后的字符串列表(list ...

  7. PHP基础语法: echo,var_dump, 常用函数:随机数:拆分字符串:explode()、rand()、日期时间:time()、字符串转化为时间戳:strtotime()可变参数的函数:PHP里数组长度表示方法:count($attr[指数组]);字符串长度:strlen($a)

    PHP语言原理:先把代码显示在源代码中,再通过浏览器解析在网页上 a. 1.substr;  //用于输出字符串中,需要的某一部分 <?PHP $a="learn php"; ...

  8. Java 数据类型之间的转换 拆分字符串 Date/Calendar的转换

    数据类型转换 1. String - Int String str="123"; int i=1; int str=Integer.parseInt(str); String i= ...

  9. C++ 拆分字符串-copy()

    c++拆分字符串方法: #include <iostream>#include <string>#include <sstream>#include <alg ...

随机推荐

  1. jQuery学习之jQuery Ajax用法详解

    jQuery Ajax在web应用开发中很常用,它主要包括有ajax,get,post,load,getscript等等这几种常用无刷新操作方法,下面我来给各位同学介绍介绍. 我们先从最简单的方法看起 ...

  2. CSS3线性渐变和径向渐变

    background:linear-gradient(to top left, blue,orange);//从右下角往左上角渐变 background:radial-gradient(to top ...

  3. 布局 - panel

    panel一般作为其他组件的容器使用 很多组件都继承自panel 对于面板中的内容,支持异步从后台加载,当然,作为纯粹的面板,一般不会用到这个,但他的子类对于这个功能还是蛮实用的 <%@ tag ...

  4. AngularJS中的指令

    欢迎大家讨论与指导 : )  前言 当AngularJS中的内置指令不能满足我们的需求,或者当我们需要创建一个能够用于多个AngularJS程序的自包含的功能单元时,我们应该创建自定义指令来满足需求. ...

  5. js profiler

    https://developers.google.com/web/fundamentals/performance/critical-rendering-path/?hl=en https://de ...

  6. C语言 自动修改文件名小程序

    #define _CRT_SECURE_NO_WARNINGS #include <stdio.h> #include <stdlib.h> #include <stri ...

  7. tar 解压缩命令详解

    今天对目录及其文件进行压缩:/usr/local/test# tar -cvf /usr/local/auto_bak/test.tar /usr/local/test 仅打包,不压缩 # tar - ...

  8. 发布了Android的App,我要开源几个组件!

    做了一款App,本来是毕业设计但是毕业的时候还没有做完,因为大部分时间都改论文去了,你们都懂的.现在毕业了在工作之余把App基本上做完了.为什么说基本上呢,因为我觉得还有很多功能还没实现,还要很多bu ...

  9. Wabpack系列:在webpack+vue开发环境中使用echarts导致编译文件过大怎么办?

    现象,在一个webpack+vue的开发环境中,npm install echarts --save了echarts,然后在vue文件中直接使用 import echarts from 'echart ...

  10. 【深入ASP.NET原理系列】--Asp.Net Mvc和Asp.Net WebForm共用一套ASP.NET请求管道

    .NET FrameWork4在系统全局配置文件(如在如下目录中C:\Windows\Microsoft.NET\Framework64\v4.0.30319\Config) 中添加了一个名字叫Url ...