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

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

        

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

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

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

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

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

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

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

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
-- 使用当前用户权限(使用authid current_user,定义type为用户当前用户的权限,举个例子:比如A用户他可以建立表,但是A用户在存储过程中如果建立表可能会提示权限不够,所以需要用authid current_user进行约束)
create or replace type wy_wm_concat authid current_user as object
(
--拼接字符串,存放中间值,当然也可以定义为clob,clob会使用临时段,导致临时表空间迅速增大;
--查看wmsys下的function可以发现Oracle10g到oracle11g自带的wm_concat函数的返回类型从clob变成varchar2
  currStr VARCHAR2(32767),
--分割字符串
  delimiter VARCHAR2(64),
--排序字符串(asc、desc)
  orderby VARCHAR2(64),
-- 定义字符串数组
  strArray WYARRAY,
-- 初始化接口函数
  STATIC FUNCTION ODCIAGGREGATEINITIALIZE(init IN OUT wy_wm_concat)
    RETURN NUMBER,
-- 迭代接口函数
  MEMBER FUNCTION ODCIAGGREGATEITERATE(self     IN OUT wy_wm_concat,
                                       colValue IN VARCHAR2) RETURN NUMBER,
-- 并行时字符串合并的接口函数
  MEMBER FUNCTION ODCIAGGREGATEMERGE(self IN OUT wy_wm_concat,
                                     next wy_wm_concat) RETURN NUMBER,
-- oracle终止接口函数
  MEMBER FUNCTION ODCIAGGREGATETERMINATE(self        IN wy_wm_concat,
                                         returnValue OUT VARCHAR2,
                                         flags       IN NUMBER)
    RETURN NUMBER
)

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

(4)自定义聚集函数

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

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

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

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

③降序排序

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

重写Oracle的wm_concat函数,自定义分隔符、排序相关推荐

  1. oracle vm concat指定分隔符,重写Oracle的wm_concat函数,自定义分隔符、排序

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

  2. Oracle中wm_concat函数报错解决方法

    Oracle中wm_concat函数报错解决方法 参考文章: (1)Oracle中wm_concat函数报错解决方法 (2)https://www.cnblogs.com/52net/archive/ ...

  3. Oracle的wm_concat()函数与Mysql的group_concat()函数

    这两个函数的作用是相同的,它们的功能是:实现行转列功能,即将查询出的某一列值使用逗号进行隔开拼接,成为一条数据. 1.Oracle的wm_concat()函数 2.Mysql的group_concat ...

  4. Oracle数据库wm_concat()函数的使用方法

    oracle数据库中wm_concat(column)函数使我们经常会使用到的,下面就教您如何使用oracle数据库wm_concat(column)函数实现字段合并 如: shopping: --- ...

  5. 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 ...

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

    解决ORA-00904: "WMSYS"."WM_CONCAT" WM_CONCAT是oracle的非公开函数,并不鼓励使用,新版本oracle并没有带此函数, ...

  7. 知识点备忘-oracle的wm_concat()函数

    今天在工作中遇到一个需求,需要把SQL语句的查询结果的列转成一行,请教同事后得知可以使用wm_concat()这个函数,现记录在此. wm_concat()用于将列转为行,列数据之间用逗号隔开,注意其 ...

  8. oracle中wm_concat函数去重,oracle-常用函数-wm_contact

    oracle wm_concat(column)函数使我们经常会使用到的,下面就教您如何使用oraclewm_concat(column)函数实现字段合并 如: shopping: --------- ...

  9. oracle 的wm_concat函数使用

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

最新文章

  1. 面向对象第四单元小结
  2. “约见”面试官系列之常见面试题第二十九篇之Vue和React的区别
  3. 21.策略模式(Strategy Pattern)
  4. django models
  5. 新成员入群监控自动发送邮件效果如何实现?
  6. 分享一个好的清理系统垃圾软件
  7. SIP协议的功能在统一通信中的体现
  8. 数据错误(循环冗余检查) 各种解决方法
  9. 【无标题】人工智能的定义
  10. 网络安全面试题目及详解
  11. 6.哈夫曼树及哈夫曼编码
  12. TM1637数码管显示
  13. amazon - amzreport 之 amazon report list
  14. frame被废除_废除用户体验设计的假神
  15. java.sql.SQLSyntaxErrorException: Table 'ph.tbl_user' doesn't exist
  16. 《32天SQL筑基》导读
  17. ACM新生赛部分题解
  18. TCP套接口的最大SYN队列长度
  19. 多多情报通:拼多多哪些类目好做?拼多多做什么类目好?
  20. 给大四实习学生的一些建议

热门文章

  1. OpenCV为轮廓创建边界框和圆
  2. C++horspool算法查找字符串是否包含子字符串(附完整源码)
  3. C++new和delete
  4. C++重载运算符最好声明为友元
  5. QML自定义图表图例
  6. QT的QOpenGLDebugLogger类的使用
  7. QT的QDBusInterface类的使用
  8. QT的QDateTimeAxis类的使用
  9. java什么是对象如何创建对象_java对象的创建过程是什么
  10. python颜色形状识别_Python自定义颜色形状Fi