Oracle 自定义函数实现列转行效果
在 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 自定义函数实现列转行效果的更多相关文章
- Mybatis下配置调用Oracle自定义函数返回的游标结果集
在ibatis和Mybatis对存储过程和函数函数的调用的配置Xml是不一样的,以下是针对Mybatis 3.2的环境进行操作的. 第一步配置Mapper的xml内容 <mapper names ...
- 【转】Oracle 自定义函数语法与实例
原文地址:https://blog.csdn.net/libertine1993/article/details/47264211 Oracle自定义函数的语法如下: create or replac ...
- Oracle自定义函数和存储过程示例,自定义函数与存储过程区别
参考资料:http://www.newbooks.com.cn/info/60861.html oracle自定义函数学习和连接运算符(||) 贴一段中文文档示例,应该就可以开始工作了: --过程(P ...
- Oracle自定义行转列函数
--行转列自定义函数,只针对TABLE1表 --paramType是参数类型,用于判断,param1和param2是条件参数 create or replace function My_concat( ...
- Oracle自定义函数1
用户定义函数是存储在数据库中的代码块,可以把值返回到调用程序.调用时如同系统函数一样,如max(value)函数,其中,value被称为参数.函数参数有3种类型. IN 参数类型:表示输入给函数的参数 ...
- Oracle自定义函数
核心提示:函数用于返回特定数据.执行时得找一个变量接收函数的返回值; 语法如下: create or replace function function_name ( argu1 [mode1] da ...
- Oracle自定义函数&加密
在sql中频繁使用的功能(逻辑.加密等)可以写成自定义函数进行封装,之后再调用即可. CREATE OR REPLACE FUNCTION "函数名" (参数名 参数类型 参数数据 ...
- oracle自定义函数:将使用点分隔符的编码转成层级码格式的编码
维护一个旧的系统,表设计中只有编码,而没有其他排序相关的字段,然后根据编码排序出现了顺序错乱的问题. 详细地说,其编码设计是使用[.]分隔符的编码,比如1.1.1.1.1.1.1.1.1.2这样的格式 ...
- oracle 逗号分割,列转行,行转列
SQL代码 列转行 select REGEXP_SUBSTR(a.rolecode ,,l) rolecode from ( select 'a,aa,aaa' rolecode from dual ...
随机推荐
- 如何利用 VisualStudio2019 遠端工具進行偵錯
Hi 這次要來介紹 如何使用 Visual Studio 2019 遠端工具進行 Release 應用程式偵錯 首先我們先下載 2019 專用的遠端工具(這裡依照不同的 VisualStudio 版本 ...
- WEBAPI 设置上传文件大小
参考资料:https://stackoverflow.com/questions/33399267/cors-error-when-uploading-larger-files https:// ...
- C# - VS2019 WinFrm应用程序连接Access数据库,并简单实现数据库表的数据查询、显示
序言 众所周知,Oracle数据库和MySQL数据库一般在大型项目中使用,在某些小型项目中Access数据库使用较为方便,今天记录一下VS2019 WinFrm应用程序连接Access数据库,并实现数 ...
- 剑指 Offer——1. 二维数组中的查找
题目描述 在一个二维数组中(每个一维数组的长度相同),每一行都按照从左到右递增的顺序排序,每一列都按照从上到下递增的顺序排序.请完成一个函数,输入这样的一个二维数组和一个整数,判断数组中是否含有该整数 ...
- 第一章 权限管理DEMO简介
源代码GitHub:https://github.com/ZhaoRd/Zrd_0001_AuthorityManagement 1.系列介绍 工作已有五年之久,一直有想通过博客写点自己知道的,在博客 ...
- mac下chm文件打开乱码解决
菜单栏点击---显示---文本编码(选择编码格式)
- warning: Unexpected unnamed function (func-names)
warning: Unexpected unnamed function (func-names) 看到这个提示基本是就是说你的函数不能是匿名函数,最好可以起一个名字,然后你增加一个函数名称就好了 R ...
- 对cell每一行做标记
通过数组进行标记 初始化列表的时候给一个值如 for (int i = 0; i < [self.tableData count]; i++) { [_allOrderBoo ...
- 一次http请求的过程
http协议(超文本传输协议)是属于应用层的协议,网络分层:应用层(http协议,FTP),传输层(tcp,udp),网络层(ip/ARP),链路层 我们以浏览器向百度发送请求为例: http的发送: ...
- time,datetime,random,os,sys,hashlib,logging,configparser,re模块
#-----time模块----- print(help(time)) #打印time帮助文档 print(time.time()) #打印时间戳 1569824501.6265268 time.sl ...