Oracle 11g行字段拼接WMSYS.WM_CONCAT问题Not A LOB
Oracle 11g行字段拼接WMSYS.WM_CONCAT问题Not A LOB
一、问题出现
项目中的某个查询需要将表中某个字段不重复地拼接起来,百度得到该函数WMSYS.WM_CONCAT(字段)
,以及listagg(字段,连接符)
函数,前者只能使用逗号',
'连接,后者可以定制连接符。
但由于listagg不能直接在参数中使用distinct
去重,因此采用WM_CONCAT
函数。
SQL格式如下:
select t.id, t.pjname
from (select A.id as id, count(distinct B.name) as countname,
to_char(wmsys.wm_concat(distinct to_char(B.name))) as pjname
from A left join B on A.id = B.id
where 1 = 1
group by A.id) t
where t.countname > 1;
这段SQL的作用是,以A表的id为组,不重复的拼接B表的name,并统计name去重后的个数,最后返回name去重后仍多于1个的id和拼接name。
开发时这段SQL是正常的,然而,这段SQL在测试库上却会报错ORA-22922: 不存在的 LOB 值
。
二、原因分析
经网上查资料,发现问题出在WMSYS.WM_CONCAT
函数在Oracle不同版本中的返回值类型不同。
该项目开发使用的是Oracle 11.2.0.1.0,而测试与现场使用的均为Oracle 11.2.0.4.0,项目开始时的疏忽导致开发与测试的不一致。
将拼接函数外的to_char去掉后,SQL不会报错,但对象不是String类型(可能是java.sql.Clob
类型),无法直接toString获得。
同时,在PLSQL Developer 9.0中直接运行SQL时,该拼接结果直接显示为<CLOB>
,可在select结果中使用to_char()
函数,而该函数在项目dal层直接运行仍报错。
三、问题解决
- 去掉WM_CONCAT函数外的to_char()
select t.id, t.pjname
from (select A.id as id, count(distinct B.name) as countname,
wmsys.wm_concat(distinct to_char(B.name)) as pjname
from A left join B on A.id = B.id
where 1 = 1
group by A.id) t
where t.countname > 1;
- 将LOB类型对象转换为String类型,有两种方法:在SQL中使用Oracle函数,或者在后端dal层转换,参考网上的文章,我选择后者,因为完整的SQL要实现的功能本身比较复杂,要尽量简化在数据库中的操作。
- 获取结果集中的字段并判断
String array1 = "";
try {
array = array[1].getClass().toString().equals("class java.lang.String") ? array[1].toString() : ClobToString((Clob) array[1]);
} catch (SQLException e) {
array14 = array[1].toString();
} catch (IOException e) {
e.printStackTrace();
}
- 转换CLOB为String对象(参考Oracle中将Clob字段转换成字符串)
public String ClobToString(Clob clob) throws SQLException, IOException {
String reString = "";
Reader is = clob.getCharacterStream();
BufferedReader br = new BufferedReader(is);
String s = br.readLine();
StringBuffer sb = new StringBuffer();
while (s != null) {
sb.append(s);
s = br.readLine();
}
reString = sb.toString();
if(br!=null){
br.close();
}
if(is!=null){
is.close();
}
return reString;
}
问题解决。还是得看看listagg方法的用法,毕竟官方兼容性强些,但觉得listagg
不如WM_CONCAT
简单易用。
三、补充
listagg(列名,'分隔符')
除了要多嵌套一层子查询,其实也挺方便的,它是从11g起才出现的聚合函数,要实现去重和统计,需要使用distinct
的多列去重。
select A.id, t.countname, t.pjname
from A
left join (SELECT id,count(name) as countname,
LISTAGG(to_char(name), ',') WITHIN GROUP(ORDER BY name) AS pjname
FROM (select distinct B.id as id, B.name as name
from B
left join C
on B.name = C.name
where C.gender = 'female')
where 1 = 1
group by id) t
on A.id = t.id
where countname is null or countname <= 1;
四、参考文章
Oracle 11g行字段拼接WMSYS.WM_CONCAT问题Not A LOB的更多相关文章
- oracle 多行变一行 wmsys.wm_concat
背景 还是那个问题,部分程序员喜欢用sql解决问题.发现了这个函数,当初真是大喜过望,现在是哭笑不得.10g支持这个函数,11好像不支持了,而且只有oracle支持,其实自己写个通用方法 ...
- Oracle 行拼接 wmsys.wm_concat扩展
将多行数据拼接成一行: --wmsys.wm_concat group by a.flowid; 但有大小限制:字符串缓冲区太小,超过varchar 4000长度.扩展:更改返回类型为clob --T ...
- Oracle数据库合并行记录,WMSYS.WM_CONCAT 函數的用法
Sql代码 select t.rank, t.Name from t_menu_item t; 10 CLARK 10 KING 10 MILLER 20 ADAMS 20 F ...
- oracle 11g行转列 列转行
行转列: SELECT * FROM src_table UNPIVOT (param_value FOR param_name IN (product_color AS 'product ...
- mysql 多个字段拼接
Mysql的查询结果行字段拼接,能够用以下两个函数实现: 1. concat函数 mysql> select concat('1','2','3') from test ; +--------- ...
- mysql函数之四:concat() mysql 多个字段拼接
语法: COUNT(DISTINCT expr ,[expr ...]) 函数使用说明:返回不同的非NULL 值数目.若找不到匹配的项,则COUNT(DISTINCT) 返回 0 Mysql的查询结果 ...
- mysql多个字段拼接
Mysql的查询结果行字段拼接,可以用下面两个函数实现: 1. concat函数 mysql') from test ; +---------------------+ ') | +--------- ...
- Oracle中将列查询结果多行逗号拼接成一个大字段
在11G以下版本中oracle有自带的函数wm_concat可以实现,如: select wm_concat(id) from table where col='1' 但是在12C版本中此函数无法使用 ...
- Oracle之多行记录变一行记录,行变列,并排序(wmsys.wm_concat)
原帖:http://www.cnblogs.com/nayitian/p/3231734.html wmsys.wm_concat Definition: The Oracle PL/SQL WM_C ...
随机推荐
- Table 边框合并(collapse)
border-collapse:collapse 用于表格属性, 表示表格的两边框合并为一条; <style type="text/css"> table { bord ...
- 2、Angular2 Directive
1.Attribute directives 2.directive的理解
- js 获取时间相关
$(document).ready(function () { var date = new Date(); var sb = ""; ...
- 网站部署中遇到的问题-网页中js,css和图片资源无法加载
问题描述: 打开的网页跑版,图片无法加载,用控制台调试发现css和js都没有加载. 原因: 没有启用IIS"静态内容". 解决方法: 设置"打开或关闭windows功能& ...
- Sass学习笔记(三)
一.Sass的控制命令 二.Sass的函数功能 sass中除了可以定义变量,还自备了一系列函数功能,主要包括:字符串函数.数字函数.列表函数.颜色函数.Instrospection函数.三元函数等.当 ...
- 微信小程序的button去边框
wxml <button class='niu'>123123</button> css niu::after{ border:none; }
- Android 自定义AlertDialog的写法和弹出软键盘和覆盖状态栏
private void showMyDialog(int layoutId){ AlertDialog myDialog = new AlertDialog.Builder(context).cre ...
- 《ArcGIS Runtime SDK for Android开发笔记》——问题集:Error:Error: File path too long on Windows, keep below 240 characters
1.前言 在使用Android Studio开发环境时,经常会爆出以下错误,虽然具体细节内容各有不同,但是说明的都是同一个问题,在windows中使用过长的路径,超过240字符. Error:Erro ...
- App后台开发架构实践笔记
1 App后台入门 1.1 App后台的功能 (1)远程存储数据: (2)消息中转. 1.2 App后台架构 架构设计的流程 (1) 根据App的设计,梳理出App的业务流程: (2) 把每个业务流程 ...
- solidity语言12
View Functions 函数声明为视图,将无权修改状态 pragma solidity ^0.4.16; contract C { function f(uint a, uint b) publ ...