转自: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. Nginx+keepalived双机热备(主从模式)

    负载均衡技术对于一个网站尤其是大型网站的web服务器集群来说是至关重要的!做好负载均衡架构,可以实现故障转移和高可用环境,避免单点故障,保证网站健康持续运行.关于负载均衡介绍,可以参考:linux负载 ...

  2. BZOJ 1087 【SCOI2005】 互不侵犯King

    Description 在N×N的棋盘里面放K个国王,使他们互不攻击,共有多少种摆放方案.国王能攻击到它上下左右,以及左上左下右上右下八个方向上附近的各一个格子,共8个格子. Input 只有一行,包 ...

  3. 推薦使用 Microsoft Anti-Cross Site Scripting Library v3.1

    原文链接:http://blog.miniasp.com/post/2009/09/27/Recommand-Microsoft-Anti-XSS-Library-V31.aspx 雖然我之前已經寫過 ...

  4. salt基本原理

            转载自: 来自:http://tech.mainwise.cn/?p=438     说明:salt是一个异构平台基础设置管理工具(虽然我们通常只用在Linux上),使用轻量级的通讯器 ...

  5. Android性能优化之Systrace工具介绍(一) _&& Systrace生成的trace.html打开空白或者打不开的解决办法

    1.必须用Chrome打开 2.在mac电脑上,可能Chrome打开也是空白,解决办法是:在chrome地址栏中输入”chrome:tracing”,然后点击load按钮load你的trace.htm ...

  6. codevs3145 汉诺塔问题

    难度等级:白银 3145 汉诺塔问题 题目描述 Description 汉诺塔问题(又称为河内塔问题),是一个大家熟知的问题.在A,B,C三根柱子上,有n个不同大小的圆盘(假设半径分别为1-n吧),一 ...

  7. 资源搜集:Git精品文章推荐,常年更新

    以下放置的是搜集到的Git精品文章,常年更新: Git 常用命令详解(二) Git版本控制软件结合GitHub从入门到精通常用命令学习手册 Pro Git(中文版)

  8. es6+react环境搭建

    工具说明 Node Koa React Webpack 项目结构 - build 客户端代码的构建文件目录 - config 项目的配置文件 - docs 项目相关的文档目录 - lib 服务端库文件 ...

  9. Python2.7-异常和工具

    来自<python学习手册第四版>第七部分,而且本书发布的时候3.1还未发布,所以针对本书的一些知识会有些滞后于python的版本,具体更多细节可以参考python的标准手册. 一.异常基 ...

  10. SQL 批量修改表结构

    项目中发现一批语言表的某个字段设的值太小了需要增大,因为涉及到很多张表,所以采用游标一张张的处理. 代码很简单 ) ) DECLARE LangTable CURSOR FOR SELECT name ...