转自: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. JS/PHP 浮点数精确运算

    php浮点数精确运算 bc是Binary Calculator的缩写.bc*函数的参数都是操作数加上一个可选的 [int scale],比如string bcadd(string $left_oper ...

  2. AFNetworking 基本使用

    AFNetwork是一个轻量级的网络请求api类库.是以NSURLConnection, NSOperation和其他方法为基础的. 下面这个例子是用来处理json请求的 3如何选择AFNetwork ...

  3. C#开发中Windows域认证登录2(扩展吉日嘎拉GPM系统)

    原文地址:http://www.cuiwenyuan.com/shanghai/post/Windows-AD-Logon-Intergrated-into-Jirigala-GPM-DotNet-B ...

  4. 打字机游戏Ⅱ之手速pk

    前言 demo预览->typewriter gameⅡ (chrome only 没做兼容) 别看一开始时速度不快,会线性增长的哦,反正楼主的score还没达到过40... 为什么叫Ⅱ呢?之前写 ...

  5. VS Code First使用Mysql数据库详解

    最近电脑出毛病了,自己装显卡驱动给装死了开不了机,自己研究了两天也没解决,只有去修电脑的找专业人员,说起来惭愧,虽然自己是搞计算机的可电脑自己重装系统都还搞不定.重装系统又清理灰尘花了50大洋,现在用 ...

  6. css的active事件在手机端不生效的解决方法

    对一名前端来说,改页面的过程总是痛苦的,产品经理说要加个点击样式,于是加active的class,本来以为这样就OK了,没想到电脑上ok,本地测也是ok的,tomcat上一跑就没效果了.我甚至把! i ...

  7. 也来山寨一版Flappy Bird (js版)

    随着Flappy Bird的火爆,各种实现的版也不断出现,于是也手痒简单实现了一版. 其实本来只是想实现一下这只笨鸟的飞翔运动的,后来没忍住,就直接实现一个完整游戏了…… 因为这个游戏本身实现起来就没 ...

  8. centos 服务器内存管理

    du su /目录/ 查看改目录大小 ls -lht /  查看文件详情,显示文件大小(直观) df -h 查看系统内存占用情况

  9. STL数组处理常用函数

    reverse(a,a+n)反转 sort(a,a+n,cmp)排序 unique(a,a+n,cmp)对于有序集合进行去重,返回新数组最后一个元素的指针 next_permutatoin(a,a+n ...

  10. webpack入坑之旅(六)配合vue-router实现SPA

    这是一系列文章,此系列所有的练习都存在了我的github仓库中vue-webpack,在本人有了新的理解与认识之后,会对文章有不定时的更正与更新.下面是目前完成的列表: webpack入坑之旅(一)不 ...