在 Oracle 领域,我相信一说到列转行大部分人都会立马想到 WM_CONCAT 函数,我觉得主要是因为该函数比较实用。但事实上 WM_CONCAT 并非官方公开函数,使用会存在一定的风险;函数返回值的格式比较单一(只能用逗号分割);返回值的长度也限制。

《.Net程序员学用Oracle系列(20):层次查询(CONNECT BY)》一文中,详细讲解了 WM_CONCAT 函数的用法。如果不用 WM_CONCAT 函数又该如何实现列转行呢?当数据类别比较少的时候,通过 CASE 判断或 UNION ALL 查询也能实现效果,但问题就是写法太死板,不过一般也没人会这么干。本文接下来会介绍两个自定义函数分别来实现列转行的聚合效果。

第一个自定义函数主要是辅以 COLLECT 函数来实现的,我在回答一个园友的问题时列出了实现步骤,查看该问题。下面是我重新整理后的版本:

第 1 步(创建类型 type_table_string,用于转换 COLLECT 函数的返回值):

CREATE OR REPLACE TYPE type_table_string IS TABLE OF VARCHAR2(4000);

第 2 步(创建函数 fn_to_string,用于将 type_table_string 类型转换成普通字符串):

CREATE OR REPLACE FUNCTION fn_to_string(
p_str_tab IN type_table_string,
p_separator IN VARCHAR2 DEFAULT ','
)
RETURN VARCHAR2 IS
v_ret_str VARCHAR2(4000);
BEGIN
FOR i IN 1..p_str_tab.COUNT LOOP
v_ret_str:=v_ret_str||p_separator||p_str_tab(i);
END LOOP;
RETURN LTRIM(v_ret_str,p_separator);
END;

调用方法:

SELECT t.dept_code,fn_to_string(CAST(COLLECT(t.staff_name) AS type_table_string),'|') staff_names
FROM demo.t_staff t GROUP BY t.dept_code;

调用结果:

DEPT_CODE                        STAFF_NAMES
-------------------------------- ----------------------------------------------
010101 小明|小强|王二
010102 小林|小萨
010103 韩三|小玲
010104 小梅|小燕
010201 小军|小芳|小红
010202 小飞

第二个自定义函数在百度中输入“zh_concat”就能找到一堆的参考,我有尝试寻找 zh_concat 函数的出处,但网上的翻版实在太多,而且大部分比较无耻(没写出处),结果就是我没能找到该函数的出处,因此在这里我也没法儿给出 zh_concat 函数的出处了。

我找到的那些有关 zh_concat 函数的帖子内容普遍比较混乱,于是我决定整理出一个更加清晰、整洁和美观的版本,以便阅读和理解,具体如下:

第 1 步(创建类型 type_concat 的定义):

CREATE OR REPLACE TYPE type_concat
AUTHID CURRENT_USER AS OBJECT(
v_result_string VARCHAR2(4000),
STATIC FUNCTION odciAggregateInitialize(
concat IN OUT type_concat) RETURN NUMBER,
MEMBER FUNCTION odciAggregateIterate(
SELF IN OUT type_concat,str IN VARCHAR2) RETURN NUMBER,
MEMBER FUNCTION odciAggregateTerminate(
SELF IN type_concat,return_value OUT VARCHAR2,flags IN NUMBER) RETURN NUMBER,
MEMBER FUNCTION odciAggregateMerge(
SELF IN OUT type_concat,concat IN type_concat) RETURN NUMBER
);

第 2 步(创建类型 type_concat 的 body):

CREATE OR REPLACE TYPE BODY type_concat
IS
STATIC FUNCTION odciAggregateInitialize(concat IN OUT type_concat)
RETURN NUMBER IS
BEGIN
concat := type_concat(NULL);
RETURN ODCICONST.SUCCESS;
END; MEMBER FUNCTION odciAggregateIterate(SELF IN OUT type_concat,str IN VARCHAR2)
RETURN NUMBER IS
BEGIN
IF SELF.v_result_string IS NOT NULL THEN
SELF.v_result_string := SELF.v_result_string||','||str;
ELSE
SELF.v_result_string := str;
END IF;
RETURN ODCICONST.SUCCESS;
END; MEMBER FUNCTION odciAggregateTerminate(SELF IN type_concat,return_value OUT VARCHAR2,flags IN NUMBER)
RETURN NUMBER IS
BEGIN
return_value := SELF.v_result_string;
RETURN ODCICONST.SUCCESS;
END; MEMBER FUNCTION odciAggregateMerge(SELF IN OUT type_concat,concat IN type_concat)
RETURN NUMBER IS
BEGIN
IF concat.v_result_string IS NOT NULL THEN
SELF.v_result_string := SELF.v_result_string||','||concat.v_result_string;
END IF;
RETURN ODCICONST.SUCCESS;
END;
END;

第 3 步(创建函数 fn_concat,可替代 WM_CONCAT):

CREATE OR REPLACE FUNCTION fn_concat(str VARCHAR2)
RETURN VARCHAR2 AGGREGATE USING type_concat;

调用方法:

SELECT t.dept_code,fn_concat(t.staff_name) staff_names FROM demo.t_staff t GROUP BY t.dept_code;

调用结果:

DEPT_CODE                             STAFF_NAMES
------------------------------------- ----------------------------------------------------
010101 小明,小强,王二
010102 小林,小萨
010103 韩三,小玲
010104 小梅,小燕
010201 小军,小芳,小红
010202 小飞

说明一:上例中的 AUTHID CURRENT_USER 是权限控制的关键字,表示调用者权限,即当前用户。默认为 AUTHID DEFINER,表示定义者权限,即模式拥有者。

说明二:将 type_concat 中 v_result_string 和 return_value 的类型改为 CLOB 类型,并将 fn_concat 的返回值类型也改为 CLOB,就成了 CLOB 版的 fn_concat 了。

本文链接http://www.cnblogs.com/hanzongze/p/oracle-wm_concat.html

版权声明:本文为博客园博主 韩宗泽 原创,作者保留署名权!欢迎通过转载、演绎或其它传播方式来使用本文,但必须在明显位置给出作者署名和本文链接!个人博客,能力有限,若有不当之处,敬请批评指正,谢谢!

Oracle 自定义函数实现列转行效果的更多相关文章

  1. Mybatis下配置调用Oracle自定义函数返回的游标结果集

    在ibatis和Mybatis对存储过程和函数函数的调用的配置Xml是不一样的,以下是针对Mybatis 3.2的环境进行操作的. 第一步配置Mapper的xml内容 <mapper names ...

  2. 【转】Oracle 自定义函数语法与实例

    原文地址:https://blog.csdn.net/libertine1993/article/details/47264211 Oracle自定义函数的语法如下: create or replac ...

  3. Oracle自定义函数和存储过程示例,自定义函数与存储过程区别

    参考资料:http://www.newbooks.com.cn/info/60861.html oracle自定义函数学习和连接运算符(||) 贴一段中文文档示例,应该就可以开始工作了: --过程(P ...

  4. Oracle自定义行转列函数

    --行转列自定义函数,只针对TABLE1表 --paramType是参数类型,用于判断,param1和param2是条件参数 create or replace function My_concat( ...

  5. Oracle自定义函数1

    用户定义函数是存储在数据库中的代码块,可以把值返回到调用程序.调用时如同系统函数一样,如max(value)函数,其中,value被称为参数.函数参数有3种类型. IN 参数类型:表示输入给函数的参数 ...

  6. Oracle自定义函数

    核心提示:函数用于返回特定数据.执行时得找一个变量接收函数的返回值; 语法如下: create or replace function function_name ( argu1 [mode1] da ...

  7. Oracle自定义函数&加密

    在sql中频繁使用的功能(逻辑.加密等)可以写成自定义函数进行封装,之后再调用即可. CREATE OR REPLACE FUNCTION "函数名" (参数名 参数类型 参数数据 ...

  8. oracle自定义函数:将使用点分隔符的编码转成层级码格式的编码

    维护一个旧的系统,表设计中只有编码,而没有其他排序相关的字段,然后根据编码排序出现了顺序错乱的问题. 详细地说,其编码设计是使用[.]分隔符的编码,比如1.1.1.1.1.1.1.1.1.2这样的格式 ...

  9. oracle 逗号分割,列转行,行转列

    SQL代码 列转行 select REGEXP_SUBSTR(a.rolecode ,,l) rolecode from ( select 'a,aa,aaa' rolecode from dual ...

随机推荐

  1. RabbitMQ、RPC、SaltStack "贡"具的使用

    消息队列 使用队列的场景 在程序系统中,例如外卖系统,订单系统,库存系统,优先级较高 发红包,发邮件,发短信,app消息推送等任务优先级很低,很适合交给消息队列去处理,以便于程序系统更快的处理其他请求 ...

  2. SPFA板子

    #pragma GCC optimize(3) #include <bits/stdc++.h> using namespace std; ; vector<pair<int, ...

  3. dtd语法

    dtd语法 <!ELEMENT 元素名 约束> //简单元素三种:没有子元素的元素 eg: <!ELEMENT name (#PCDATA)> (#PCDATA):约束name ...

  4. mac os catalina mongodb最新安装流程

    1.brew安装 不推荐用brew,因为现在mongodb闭源了,brew里已经搜索不到mongodb,不过还是可以用brew安装的,这篇就不写了. 2.官网下载 直接去官网下载一个zip,解压完放到 ...

  5. authenticating with the app store 一直卡住--问题记录

    参考链接:https://blog.csdn.net/csdn2314/article/details/90021367 authenticating with the app store 一直卡住最 ...

  6. docker研究-3 docker简介和基本操作

    Docker是PaaS供应商dotCloud开源的一个基于LXC 的高级容器引擎,源代码托管在 GitHub 上, 基于Go语言开发并遵从Apache 2.0协议开源.Docker 是通过内核虚拟化技 ...

  7. Highways POJ - 1751

    题目链接:https://vjudge.net/problem/POJ-1751 思路: 最小生成树板子,只需要多记录每个dis[x]的权值是从哪个点到x这个点的. #include <stdi ...

  8. 201871010134-周英杰《面向对象程序设计(java)》第十四周学习总结

    项目 内容 这个作业属于哪个课程 <https://home.cnblogs.com/u/nwnu-daizh/> 这个作业的要求在哪里 <https://www.cnblogs.c ...

  9. Maven 中 dependencyManagement 元素,知识点

    Maven 提供的 dependencyManagement 元素既能让子模块继承到父模块的依赖配置,又能保证子模块依赖使用的灵活性.在 dependencyManagement 元素下的依赖声明不会 ...

  10. 13-numpy笔记-莫烦pandas-1

    代码 import pandas as pd import numpy as np s = pd.Series([1,3,6,np.nan, 44,1]) print('-1-') print(s) ...