一、背景

在数据开发中,有时你需要合并两个动态游标sys_refcursor

开发一个存储过程PROC_A,这个过程业务逻辑相当复杂,代码篇幅较长。一段时间后要开发一个PROC_B,要用PROC_A同样的逻辑,而且在这个过程中,还要循环调用PROC_A这个过程。摆在你面前的有两个选择。

  • 打开PL/SQL,仔细的读PROC_A这个过程,一直到明白了所有的逻辑,然后在自己的过程中重写这个逻辑 。
  • 直接复制PROC_A这个过的代码过来,多写极端。还是业界标准大法好
  • 针对循环调用的,建立一个临时表,循环插入数据到临时表(但这里还有一个问题,每次返回的游标可能列都不相同,建立临时表就显得复杂了)

好吧,这个新的过程是完成了,可是看上去,它更复杂了,代码量更大了。完全不能接受,必须改改!
这时,已经默默打开了ORACLE官方帮助文档 https://docs.oracle.com/cd/B19306_01/index.htm,寻找一个可行的办法,最终目标标是要解析,整合,合并 游标 sys_refcursor

二、思路

经过搜索查询,找到以下可行的方案

  1. 序列化sys_refcursor为xml文档,ORACLE对xml支持还不错,12C已经有JSON格式了
  2. 使用ORACLE xml解析的方法,对序列化的xml文档,添加、删除、修改
  3. 转换为内存表,通过游标返回查询的结果

为此你需要掌握的知识有

三、实现

从上边的帮助文档中,知道xmltype的构造函数中可以直接传入游标xmltype(refcursor)从而得到一个xmltype,调用xmltype的getClobVal方法,可得到序列化的结果,所以它的结构是这样的

 <?xml version="1.0"?>
<ROWSET>
<ROW>
<COLUMNNAME1></COLUMNNAME1>
<COLUMNNAME2></COLUMNNAME2>
<...>...</...>
</ROW>
....
</ROWSET>

所以,如果需要合并两个数据列相同游标,只需要提取DOM中的ROW节点数据保存到定义的clob字段中去。

提取dom中片段,采用标准的xpath语法,/ROWSET/ROW这里提取ROW信息

 Declare
x xmltype;
rowxml clob;
mergeXml clob;
ref_cur Sys_Refcursor;
ref_cur2 Sys_Refcursor;
ref_cur3 Sys_Refcursor;
begin
9 open ref_cur for
10 select F_USERNAME, F_USERCODE, F_USERID
from Tb_System_User
where F_userid = 1;
Dbms_Lob.createtemporary(mergeXml, true);
14 Dbms_Lob.writeappend(mergeXml, 8, '<ROWSET>');
x := xmltype(ref_cur);
Dbms_Output.put_line('=====完整的REFCURSOR结构=====');
Dbms_Output.put_line(x.getClobVal());
Dbms_Output.put_line('=====只提取行信息=====');
rowxml := x.extract('/ROWSET/ROW').getClobVal(0, 0);
Dbms_Output.put_line(rowxml);
Dbms_Lob.append(mergeXml, rowxml);ROWSET
open ref_cur2 for
select F_USERNAME, F_USERCODE, F_USERID
from Tb_System_User
where F_userid = 1000;
x := xmltype(ref_cur2);
rowxml := x.extract('/ROWSET/ROW').getClobVal(0, 0);
Dbms_Lob.append(mergeXml, rowxml);
Dbms_Lob.writeappend(mergeXml, 9, '</ROWSET>');
Dbms_Output.put_line('=====合并后的信息=====');
Dbms_Output.put_line(mergeXml);
end;

执行这段代码输出的结果是这样的

 =====完整的REFCURSOR结构=====
<?xml version="1.0"?>
<ROWSET>
<ROW>
<F_USERNAME>系统管理员</F_USERNAME>
<F_USERCODE>admin</F_USERCODE>
<F_USERID>1</F_USERID>
</ROW>
</ROWSET> =====只提取行信息=====
<ROW>
<F_USERNAME>系统管理员</F_USERNAME>
<F_USERCODE>admin</F_USERCODE>
<F_USERID>1</F_USERID>
</ROW> =====合并后的信息=====
<ROWSET><ROW>
<F_USERNAME>系统管理员</F_USERNAME>
<F_USERCODE>admin</F_USERCODE>
<F_USERID>1</F_USERID>
</ROW>
<ROW>
<F_USERNAME>黄燕</F_USERNAME>
<F_USERCODE>HUANGYAN</F_USERCODE>
<F_USERID>1000</F_USERID>
</ROW>
</ROWSET>

从上边打印的结果看,我们已经成功的将两个游标 ref_curref_cur2中我们需要的列信息合并到了一个xml文档中。那么接下了,我们就需要通过解析这个xml并返回一个新的sys_refcursor,这里你有必要了解以下oracle xmltable的用法(https://docs.oracle.com/cd/B19306_01/server.102/b14200/functions228.htm)接上边代码

 Dbms_Output.put_line(mergeXml);
open ref_cur3 for
select *
from xmltable('/ROWSET/ROW' Passing xmltype(mergeXml) Columns
F_USERNAME varchar2(100) path 'F_USERNAME',
F_USERCODE varchar2(100) path 'F_USERCODE'); 

简单说明下xmltable构造函数

  • 声明xpath,指明你需要解析的dom在哪里,比如从根找到ROW /ROWSET/ROW
  • 指明你要查询的xmltype
  • 定义转换列,比如把ROW下边的F_USERNAME这个节点值,映射到游标列F_USERNAME 这个列中

四、总结

xml作为早期数据传输,序列化和反序列化的文件格式,在oracle中也有良好的支持。所以,对于基于语言之上的知识,各个语言实现方式基本相识。基础终究是重要的。

oracle 合并多个sys_refcursor的更多相关文章

  1. Sun 与 Oracle 合并的未来

    引言 SUN 2008 初 10 亿美元收购 MySQL Oracle 2009 年 4 月 74 亿美元收购 SUN Sun 与 Oracle 合并的未来 1,如果云计算对企业来说变得越来越重要,那 ...

  2. oracle合并语句

    在sql server中的合并语句可以用xml path 详见http://www.cnblogs.com/codeyu/archive/2010/05/25/1743474.html 而oracle ...

  3. Oracle合并函数内容

    --MINUS去差集,取第一个集合有的而第二集合没有的,并以第一个字段排序select t.bumenbm from T_HQ_BM t minus select b.bumenbm from t_h ...

  4. Oracle ref cursor和sys_refcursor

    1. 自定义 ref cursor 和 sys_refcursor; 2. sys_refcursor 做为参数传递结果集; 3. ref cursor 做为参数传递结果集; 1. 自定义 ref c ...

  5. Oracle合并某一列

    本文转载自:https://www.cnblogs.com/LeiYang5237/p/6761183.html 一.oracle11g使用listagg() within group()函数 如图一 ...

  6. Oracle 合并查询

    8).合并查询有时在实际应用中,为了合并多个select语句的结果,可以使用集合操作符号union,union all,intersect,minus.多用于数据量比较大的数据局库,运行速度快.1). ...

  7. oracle合并版本

    1)   添加字段,并自增 第一步:alter table TOWN add ID int 第二步:Update TOWN set id=rownum; Commit; 2)   更新表(另一张表) ...

  8. oracle合并查询

    1). Union 该操作符用于取得两个结果集的并集.当使用该操作符时,会自动去掉结果集中重复行. 2).union all 该操作符与union相似,但是它不会取消重复行,而且不会排序. 3). I ...

  9. Oracle 合并 merger into

    merge into copy_emp1 c  using employees e  on (c.employee_id=e.employee_id)when matched then  update ...

随机推荐

  1. Java读取证书

    import java.io.FileInputStream; import java.security.Key; import java.security.KeyFactory; import ja ...

  2. Java 后台POST模拟文件上传

    概述 废话不多说,直接撸代码 代码 1.引入Maven包 <dependency> <groupId>org.apache.httpcomponents</groupId ...

  3. 杂记:腾讯暑期实习 Web 后端开发面试经历

    今天面试(一面)腾讯暑期实习 Web 后端开发,一言难尽. 第一部分,常规的自我介绍. 介绍完,面试官问我对人工智能有什么理解?深度学习和机器学习的区别?对调参有什么见解?语音识别中怎样运用了机器学习 ...

  4. html_jQuery_ajax

    ajax核心对象:  XMLHttpRequest 那年创建的XMLHttpRequest对象 创建的.. ajax 几种常用方法: load(); $.get(); $.post(); $.getS ...

  5. docker配置nginx做反向代理管理tomcat应用

    由于业务开始复杂,单一tomcat已经不足以满足业务需求,多tomcat部署起来不方便而且面临域名解析问题,因此开始增加反向代理,由于docker的易用性,便使用docker管理各个应用. docke ...

  6. 课下必做MyCP

    一.Linux的CP命令 Linux 的cp命令 功能: 复制文件或目录 说明: cp指令用于复制文件或目录,如同时指定两个以上的文件或目录,且最后的目的地是一个已经存在的目录,则它会把前面指定的所有 ...

  7. 做IT,必备的安全知识!

    以前的认知 以前刚接触IT行业,而我身为运维,我以为我所需要做的安全就是修改服务器密码为复杂的,ssh端口改为非22,还有就是不让人登录服务器就可以保证我维护的东西安全. 现在的认知 工作也好几年了, ...

  8. ios6和ios5横竖屏切换

    记录于2013/8/5   在切换横竖屏的时候调用到的一些委托方法: #pragma mark - UIApplicationDelegate //写在Appdelegate中,在具体的某一视图控制器 ...

  9. jquery ajax中success与complete的执行顺序

    jquery ajax中success与complete的执行顺序 jquery中各个事件执行顺序如下: 1.ajaxStart(全局事件) 2.beforeSend 3.ajaxSend(全局事件) ...

  10. BZOJ 3864

    dp of dp 我就是来贴个代码 #include<bits/stdc++.h> using namespace std; #define rep(i,a,b) for(int i=(a ...