在 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. DataTable 转List

    忘了出处   ,这个是转别人的 public class DataToList<T> where T : new() { /// <summary> /// 利用反射和泛型 / ...

  2. Vue内置组件[回顾]

    1.动态组件 在某些场景,往往需要我们动态切换页面部分区域的视图,这个时候内置组件component就显得尤为重要. component接收一个名为is的属性,is的值应为父组件中注册过的组件的名称, ...

  3. java SSM 框架 微信自定义菜单 快递接口 SpringMVC mybatis redis shiro ehcache websocket

    A 调用摄像头拍照,自定义裁剪编辑头像,头像图片色度调节B 集成代码生成器 [正反双向](单表.主表.明细表.树形表,快速开发利器)+快速表单构建器 freemaker模版技术 ,0个代码不用写,生成 ...

  4. spring原理之四种基本标签的解析

    四种标签 在spring的配置文件中存在四种基本的标签分别是:beans,bean,import,alias 四种标签的功能: beans:定义一个单独的应用配置(测试配置,开发配置等),在服务器部署 ...

  5. SQL注入:Cookie注入

    什么是Cookie Cookie就是代表你身份的一串字符串,网站根据Cookie来识别你是谁,如果你获取了管理员的Cookie,就表示你可以无需密码直接登陆管理员账号. Cookie注入的原理 在动态 ...

  6. IEDA创建Springboot项目

    随着技术的更新对于开发速度的追求,我们越来越不能忍受的是Spring框架对于集成开发以后大量的配置问题.所以SprigBoot应运而生,SpringBoot框架其实就是在Spring框架的外边包裹上了 ...

  7. 安装教程-VMware 12 安装 Windows 10 企业版

    VMware 12 安装 Windows 10 企业版 1.实验描述 在虚拟机中,手动安装 Windows10 企业版操作系统,为一些实验提供平台,因此,有关系统激活问题不再演示.可自行百度,或者加入 ...

  8. nacos 实现同机器上启动三个服务

    1.我们要在单台服务器上启动多个nacos实例,保证三个不同的端口,我们可以通过修改启动脚本: 打开启动脚本找到:export FUNCTION_MODE="all"    这一行 ...

  9. ssh登录缓慢,输入账户密码等待时间长

    vim /etc/ssh/sshd_config #取消ssh的反向dns解析 UseDNS no #关闭ssh的gssapi认证 GSSAPIAuthentication no #排查是否日志文件过 ...

  10. XSS-DOM

    DOM型XSS是基于DOM文档对象模型的一种漏洞 通过 HTML DOM,树中的所有节点均可通过 JavaScript 进行访问.所有 HTML 元素(节点)均可被修改,也可以创建或删除节点.(引用W ...