Oracle中LONG类型转字符串及LIST_AGG聚合分组问题咨询
Oracle中LONG类型转字符串及LIST_AGG聚合分组问题咨询
Hey 你好呀~ 我太懂你这种被Oracle LONG类型坑到的感受了!毕竟这个老古董类型对很多聚合函数都不兼容,更别说你还是只读权限,没法改表结构来规避,确实头疼😮💨
针对你的需求,我给你两个可行的方向:
1. 纯SQL层面解决(只读权限可用)
因为LONG类型没法直接用LIST_AGG,所以第一步得把它转成CLOB类型——毕竟CLOB是Oracle里更灵活的大文本类型,大部分函数都支持。这里可以用DBMS_XMLGEN包来做转换,它在只读权限下一般是开放的:
WITH converted_to_clob AS ( SELECT table_name, -- 把LONG类型的search_condition转成CLOB XMLCAST( XMLQUERY('/ROWSET/ROW/SEARCH_CONDITION/text()' PASSING DBMS_XMLGEN.GETXMLTYPE( 'SELECT search_condition FROM check_ddls WHERE table_name = ''' || table_name || '''' ) RETURNING CONTENT ) AS CLOB ) AS search_condition_clob FROM check_ddls ) SELECT table_name, -- 用XMLAGG来拼接CLOB内容,最后去掉末尾多余的分号 RTRIM( XMLAGG( XMLELEMENT(e, search_condition_clob || ';').EXTRACT('//text()') ORDER BY table_name ).GETCLOBVAL(), ';' ) AS grouped_search_conditions FROM converted_to_clob GROUP BY table_name;
这里用XMLAGG而不是直接LIST_AGG是因为如果内容较长,LIST_AGG的VARCHAR2长度限制可能不够,XMLAGG生成CLOB就没这个问题啦。
2. 结合Java处理(符合你提到的思路)
如果SQL层面的转换遇到权限或者性能问题,那完全可以按你说的,用Java来处理:
- 首先用JDBC连接Oracle,执行查询
SELECT table_name, search_condition FROM check_ddls - 注意读取
search_condition的时候,别用getString(),而是用getAsciiStream()或者getBinaryStream()来获取LONG类型的字节流 - 在Java里用一个
Map<String, StringBuilder>来分组,key是table_name,value是用来拼接的StringBuilder - 每读取一行,就把字节流转成字符串,追加到对应table_name的StringBuilder后面,再加上分号
- 最后遍历Map,就能得到每个分组下用分号分隔的search_condition内容啦
这个方法的好处是完全绕开了Oracle对LONG类型的聚合限制,而且只读权限下JDBC的流读取是完全支持的,非常灵活。
内容来源于stack exchange




