转自: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. 兼容IE678的placeholder

    jquery-placeholder.js是基于jquery的插件,对不支持placeholder的浏览器有非常好的兼容性,只需引入这个js文件,然后给所有Input元素调用一下placeholder ...

  2. HTML 学习笔记 CSS样式(边框)

    元素的边框(border)是围绕元素内容和内边距的一条或多条线 CSS border 属性允许你规定边框的样式 宽度和颜色 CSS 边框 在 HTML 中,我们使用表格来创建文本周围的边框,但是通过使 ...

  3. BZOJ 2190: [SDOI2008]仪仗队

    2190: [SDOI2008]仪仗队 Time Limit: 10 Sec  Memory Limit: 259 MBSubmit: 2689  Solved: 1713[Submit][Statu ...

  4. switch2osm使用open street map离线地图中文乱码方框解决办法

    ----------written by shenwenkai------------- ubuntu linux环境下,按照网址(https://switch2osm.org/serving-til ...

  5. Winfrom动态创建控件

    FlowLayoutPanel flowLayoutPanel1 = new FlowLayoutPanel();for (int i = 0; i < 9; i++){    Button b ...

  6. oracle:如何用sql生成日历

    BI分析中,经常需要将事实表与时间维度表关联起来,按年/月/日来逐层展示,常用的做法是创建一张日历表,结构类似如下: create table T_BAS_CALENDAR ( d_year ) no ...

  7. Use Dapper ORM With ASP.NET Core

    Dapper.NET is not just another ORM tool, it's considered as the king of ORM. Because it's fast, easy ...

  8. 与Python Falling In Love_Python跨台阶(面向对象)

    第二课会介绍Python中的一些变量的使用.列表.元组.字典等一些详细内容...篇幅会比较多...因此在整理中... 先跳过第二课...直接来第三课..Python中面向对象的学习以及与mysql数据 ...

  9. 细数Javascript技术栈中的四种依赖注入

    作为面向对象编程中实现控制反转(Inversion of Control,下文称IoC)最常见的技术手段之一,依赖注入(Dependency Injection,下文称DI)可谓在OOP编程中大行其道 ...

  10. BGP--边界网关协议

    要全面了解BGP,首先我们要回答以下看上去很简单的问题:为什么需要BGP,也就是说BGP是如何产生的,它解决了什么问题.带着以上问题,我们先简单的回顾一个路由协议发展的轨迹. 首先路由的实质是描述一个 ...