oracle中,wm_concat函数是一个聚合函数,和mysql中的group_concat函数类似,不过group_concat函数比较强大,可以定义分隔符和排序,当然所谓强大是相对的,这里假使我们不知道oracle中的over函数,也不知道listagg函数。

我们先来看看wm_concat函数能实现什么功能,通俗点==>列传行,如果不明白,请看下面截图(可以看到分隔符默认为','顺序也是杂乱的)

        

所以,接下来,我们开始重写wm_concat函数(需要注意和需要说明的地方放在代码注释中...)

(1) 因为需要进行排序,首先自定义一个可变数组

  1. -- 定义可变数组,字符串类型,长度32767,存放列值
  2. CREATE OR REPLACE TYPE WYARRAY as TABLE OF VARCHAR(32767) ;

(2)自定义排序函数、分隔符函数

  1. -- 定义分隔符函数
  2. create or replace function delimiter(colValue in varchar2,
  3. delimiter in varchar2) return varchar2 is
  4. rtnValue varchar2(32767);
  5.  
  6. begin
  7.  
  8. rtnValue := colValue || ' delimiter=>' || delimiter || '; ';
  9.  
  10. return rtnValue;
  11.  
  12. end delimiter;

  

  1. -- 定义排序函数
  2. create or replace function orderby(colValue in varchar2,
  3. orderby in varchar2) return varchar2 is
  4. rtnValue varchar2(32767);
  5.  
  6. begin
  7.  
  8. rtnValue := colValue || ' orderby=>' || LOWER(orderby) || '; ';
  9.  
  10. return rtnValue;
  11.  
  12. end orderby;

 

(3) 重定义oracle接口函数、以及接口函数的实现体(实现分隔符和排序的主要代码)

  1. -- 使用当前用户权限(使用authid current_user,定义type为用户当前用户的权限,举个例子:比如A用户他可以建立表,但是A用户在存储过程中如果建立表可能会提示权限不够,所以需要用authid current_user进行约束)
  2. create or replace type wy_wm_concat authid current_user as object
  3. (
  4.  
  5. --拼接字符串,存放中间值,当然也可以定义为clobclob会使用临时段,导致临时表空间迅速增大;
  6. --查看wmsys下的function可以发现Oracle10goracle11g自带的wm_concat函数的返回类型从clob变成varchar2
  7. currStr VARCHAR2(32767),
  8.  
  9. --分割字符串
  10. delimiter VARCHAR2(64),
  11.  
  12. --排序字符串(ascdesc)
  13. orderby VARCHAR2(64),
  14.  
  15. -- 定义字符串数组
  16. strArray WYARRAY,
  17.  
  18. -- 初始化接口函数
  19. STATIC FUNCTION ODCIAGGREGATEINITIALIZE(init IN OUT wy_wm_concat)
  20. RETURN NUMBER,
  21.  
  22. -- 迭代接口函数
  23. MEMBER FUNCTION ODCIAGGREGATEITERATE(self IN OUT wy_wm_concat,
  24. colValue IN VARCHAR2) RETURN NUMBER,
  25.  
  26. -- 并行时字符串合并的接口函数
  27. MEMBER FUNCTION ODCIAGGREGATEMERGE(self IN OUT wy_wm_concat,
  28. next wy_wm_concat) RETURN NUMBER,
  29.  
  30. -- oracle终止接口函数
  31. MEMBER FUNCTION ODCIAGGREGATETERMINATE(self IN wy_wm_concat,
  32. returnValue OUT VARCHAR2,
  33. flags IN NUMBER)
  34. RETURN NUMBER
  35. )
  1. create or replace type body wy_wm_concat is --定义函数的body
  2.  
  3. --初始化函数
  4. STATIC FUNCTION ODCIAGGREGATEINITIALIZE(init IN OUT wy_wm_concat)
  5. RETURN NUMBER is
  6. begin
  7. init := wy_wm_concat('', ',', 'asc', WYARRAY());
  8. return ODCICONST.Success;
  9. END;
  10.  
  11. -- 字符串拼接,self 为当前聚集函数的指针,用来与前面的计算结果进行关联
  12. MEMBER FUNCTION ODCIAGGREGATEITERATE(self IN OUT wy_wm_concat,
  13. colValue IN VARCHAR2) RETURN NUMBER is
  14.  
  15. tempStr varchar(500);
  16.  
  17. extendStr varchar(500);
  18.  
  19. deStr varchar(100);
  20.  
  21. deLen int default 0;
  22.  
  23. segStr varchar(500);
  24.  
  25. --定义一个二维数组
  26. TYPE varArry IS VARRAY(2) OF VARCHAR2(200);
  27.  
  28. tempArry varArry := varArry('', '');
  29.  
  30. begin
  31.  
  32. if instr(colValue, ' ', 1) > 0 then
  33. tempStr := substr(colValue, 1, instr(colValue, ' ', 1) - 1);
  34. else
  35. tempStr := colValue;
  36. end if;
  37.  
  38. --排序和分隔符
  39. extendStr := REPLACE(colValue, tempStr || ' ');
  40.  
  41. if instr(extendStr, ' ', 1) > 0 then
  42.  
  43. tempArry(1) := substr(extendStr, 1, instr(extendStr, ' ', 1) - 1);
  44.  
  45. tempArry(2) := substr(extendStr, instr(extendStr, ' ', 1));
  46.  
  47. for i in 1 .. tempArry.count loop
  48. -- 获取分隔符
  49. if (tempArry(i) is not null) and
  50. (instr(tempArry(i), 'delimiter=>') > 0) THEN
  51.  
  52. deStr := 'delimiter=>';
  53.  
  54. deLen := length(deStr);
  55.  
  56. segStr := substr(trim(tempArry(i)),
  57. instr(trim(tempArry(i)), deStr) + deLen);
  58.  
  59. self.delimiter := SUBSTR(segStr, 1, instr(segStr, ';', -1) - 1);
  60. END IF;
  61.  
  62. -- 获取排序字符串
  63. if tempArry(i) is not null and
  64. (instr(tempArry(i), 'orderby=>') > 0) THEN
  65.  
  66. deStr := 'orderby=>';
  67.  
  68. deLen := length(deStr);
  69.  
  70. segStr := substr(trim(tempArry(i)),
  71. instr(trim(tempArry(i)), deStr) + deLen);
  72.  
  73. self.orderby := SUBSTR(segStr, 1, instr(segStr, ';', -1) - 1);
  74.  
  75. END IF;
  76.  
  77. end loop;
  78.  
  79. end if;
  80.  
  81. -- 存放入数组
  82. self.strArray.extend;
  83.  
  84. self.strArray(self.strArray.count) := tempStr;
  85.  
  86. return ODCICONST.Success;
  87. END;
  88.  
  89. --并行操作是用来合并两个聚集函数的两个不同的指针对应的结果
  90. MEMBER FUNCTION ODCIAGGREGATEMERGE(self IN OUT wy_wm_concat,
  91. next wy_wm_concat) RETURN NUMBER is
  92. begin
  93.  
  94. -- next数组中元素全部放入self指针对应的数组中
  95. for i in 1 .. next.strArray.count loop
  96.  
  97. self.strArray.extend;
  98.  
  99. self.strArray(self.strArray.count) := next.strArray(i);
  100.  
  101. end loop;
  102.  
  103. return ODCICONST.Success;
  104. END;
  105.  
  106. -- 终止函数,返回结果
  107. MEMBER FUNCTION ODCIAGGREGATETERMINATE(self IN wy_wm_concat,
  108. returnValue OUT VARCHAR2,
  109. flags IN NUMBER) RETURN NUMBER IS
  110. temp_rtnValue varchar2(32767);
  111.  
  112. BEGIN
  113. -- 排序
  114. if INSTR(self.orderby, 'desc') > 0 THEN
  115.  
  116. for x in (select column_value
  117. from Table(self.strArray)
  118. order by 1 DESC) loop
  119.  
  120. temp_rtnValue := temp_rtnValue || self.delimiter || x.column_value;
  121.  
  122. end loop;
  123. ELSE
  124. for x in (select column_value from Table(self.strArray) order by 1 ASC) loop
  125.  
  126. temp_rtnValue := temp_rtnValue || self.delimiter || x.column_value;
  127.  
  128. end loop;
  129.  
  130. END IF;
  131.  
  132. returnValue := ltrim(temp_rtnValue, self.delimiter);
  133.  
  134. return ODCICONST.Success;
  135. END;
  136.  
  137. END;

 

(4)自定义聚集函数

  1. -- 定义聚集函数(未开启并行计算功能)
  2. create or replace function wy_concat(colValue VARCHAR2) RETURN VARCHAR2
  3. AGGREGATE USING wy_wm_concat;

  

至此,主要的代码已经全部奉上,看看运行效果,如下截图:

①看看调用的默认情况(分隔符默认是逗号,排序默认是升序,在初始化函数中如此定义的)

②自定义分隔符(利用分隔符函数将分隔符定义为*)

③降序排序

④去重,为了可以使用wm_concat自带的去重函数,所以在自定义分隔符和排序函数时,实质是实用了字符串处理(如果你觉得处理字符串麻烦,可以自定义 type... as object ,在使用的时候可以很方便,不会用的童鞋可以私下问)

重写Oracle的wm_concat函数,自定义分隔符、排序的更多相关文章

  1. Oracle中wm_concat()函数的使用

    Oracle中wm_concat()函数的使用 wm_concat()函数是oracle行列转换函数,该函数可以把列值以‘,’分割开来,并显示成一行. 1.原数据: 2.把结果分组以‘|’分隔,以一行 ...

  2. Oracle创建WM_CONCAT函数

    Oracle创建WM_CONCAT函数 WM_CONCAT这个函数会出错,所以从 11g开始.官方不认可 WM_CONCAT.然后就没这个函数了, 下面就是创建WM_CONCAT这个函数的步骤 第一步 ...

  3. Oracle的wm_concat函数(转)

    wm_concat函数简单说就是行转列显示. 转自:http://christy-fang.iteye.com/blog/1299850 首先让我们来看看这个神奇的函数wm_concat(列名),该函 ...

  4. oracle的wm_concat函数实现行转列

    有以下数据 deptname phone username isboss 部门A 电话1 员工A 0 部门A 电话1 领导A 1 部门B 电话2 员工B 0 部门B 电话2 员工C 0 部门B 电话2 ...

  5. Oracle没有WM_CONCAT函数的解决办法

    WM_CONCAT是oracle的非公开函数,并不鼓励使用,新版本oracle并没有带此函数,需要手工加上. 1.下载三个文件:owmctab.plb  . owmaggrs.plb . owmagg ...

  6. oracle 的wm_concat函数使用

    转载自:http://blog.itpub.net/post/42245/522757 首先让我们来看看这个神奇的函数wm_concat(列名),该函数可以把列值以","号分隔起来 ...

  7. oracle 行列转换函数之WM_CONCAT和LISTAGG的使用(一)

    一.wm_concat函数 wm_concat能够实现同样的功能,但是有时在11g中使用需要用to_char()进行转换,否则会出现不兼容现象(WMSYS.WM_CONCAT: 依赖WMSYS 用户, ...

  8. ORACLE自定义顺序排序-转

    ORACLE可以借助DECODE函数,自定义顺序排序: select * from ( select 'Nick' as item from dual union all select 'Viki' ...

  9. oracle wm_concat 函数无法使用的情况下,使用LISTAGG()函数

    http://dacoolbaby.iteye.com/blog/1698957 --20180327 重写wm_concat函数,解决行数超过上限问题 /*执行前请将APPS替换为当前登录用户*/ ...

随机推荐

  1. JVM监控工具介绍

    JVM监控工具介绍 VisualVM是一种集成了多个JDK命令行工具的可视化工具,它能为您提供强大的分析能力.所有这些都是免费的!它囊括的命令行工具包括jps,jstat,jmap,jinfo,jst ...

  2. (转)SQL 优化原则

    一.问题的提出 在应用系统开发初期,由于开发数据库数据比较少,对于查询SQL语句,复杂视图的的编写等体会不出SQL语句各种写法的性能优劣,但是如果将应用 系统提交实际应用后,随着数据库中数据的增加,系 ...

  3. [deviceone开发]-利用do_ListView模拟单选功能

    一.简介 这个是利用do_ListView组件实现多个选项里选择一项的功能,示例很简单,但是有助于理解复用机制,也可以直接参考使用.初学者推荐.二.效果图 三.相关下载 https://github. ...

  4. ArcSDE给Oracle添加SDE函数包

    SDE函数包中包含大量的空间计算分析函数,是我们做空间相关分析的一把利刃(目前好像我们只有这一把),有关SDE函数的使用,请见我空间另外的一篇帖子的附件.按照通常教程,过程是这样的1.找到listen ...

  5. eclipse启动的时候报错 出现Java was started but returned exit code=13

    eclipse启动的时候出现 这是你的jdk环境与你eclipse版本不匹配, 如果你的eclipse是32位的 jdk也得是32位的   重新安装一个比配的jdk就好了 如果你的jdk是解压版的   ...

  6. Android 更新UI的几种方式

    1.Activity的 runOnUiThread textView = (TextView) findViewById( R.id.tv ); new Thread(new Runnable() { ...

  7. CoreData数据库浅析

    Core Data是iOS5之后才出现的一个框架,它提供了对象-关系映射(ORM)的功能,即能够将OC对象转化成数据,保存在SQLite数据库文件中,也能够将保存在数据库中的数据还原成OC对象.在此数 ...

  8. Linux的NTP配置总结

    在Linux系统中,为了避免主机时间因为在长时间运行下所导致的时间偏差,进行时间同步(synchronize)的工作是非常必要的.Linux系统下,一般使用ntp服务来同步不同机器的时间.NTP 是网 ...

  9. Function.prototype.call 和 Function.prototype.apply 的区别

    call和apply函数是function函数的基本属性,都可以用于更改函数对象和传递参数,是前端工程师常用的函数.具体使用方法请参考以下案列: 例如: 申明函数: var fn = function ...

  10. 深入理解java内存模型系列文章

    转载关于java内存模型的系列文章,写的非常好. 深入理解java内存模型(一)--基础 深入理解java内存模型(二)--重排序 深入理解java内存模型(三)--顺序一致性 深入理解java内存模 ...