Oracle SQL-LISTAGG将被称为EVEN CASE语句的条件将不会填满
我必须在版本为Oracle Database 12c Release 12.1.0.1.0 - 64bit Production
的oracle DB服务器上工作。因此,在使用LISTAGG函数时,我不能使用ON OVERFLOW ...
。为了克服大小大于4000字节的列的聚合,我希望使用提到的建议解决方案here,这样我就不会收到错误01489. 00000 - "result of string concatenation is too long"
。
不幸的是,这种方法对我不起作用。即使条件为1=1(不应调用LISTAGG函数),我也会收到上述错误。
此处查询:
select distinct t.id,
(case when 1=1 then
'Test'
else
LISTAGG(mh.RNAME1, '; ') WITHIN GROUP (ORDER BY mh.RNAME1)
end) as RNAME1LIST,
(case when 1=1 then
'Test'
else
LISTAGG(mh.RNAME2, '; ') WITHIN GROUP (ORDER BY mh.RNAME2)
end) as RNAME2LIST,
t.email1 as EMAIL1
from mh
join mp on MH.MID = MP.MID
RIGHT JOIN T ON mh.T_ID = T.ID
group by t.id, t.email1;
我正在寻找此行为的解释和替代方法,这样我就不会收到提到的错误。
解决方案
这是因为聚合实际上是在ORACLE评估行组时在飞翔上进行的,但是case
表达式位于select
列表中,因此对结果数据集进行了评估。
select
列表中,您可以将聚合结果与同一表达式中的group by
列一起使用,这也可能引入循环依赖。
下面是要查看的一些日志记录函数的示例,无论case
结果如何,它都是在聚合步骤计算的。并在聚合之后评估case
。
/*Logging table*/ create table t ( /*To have a sequence*/ id number GENERATED ALWAYS as IDENTITY(START with 1 INCREMENT by 1) , val number , src varchar2(100) )
/*Logger to check what is going on here*/ create function f_test( p_val in number , p_src in varchar2 ) return varchar2 as pragma autonomous_transaction; begin insert into t(val, src) values (p_val, p_src); commit; return p_val; end; /
/*Log aggregation function invocation and case/where evaluation*/ with a as ( select level as l , mod(level, 3) as grp from dual connect by level < 7 ) select grp , case when f_test(grp, 'CASE CONDITION') > 0 then f_test(grp, 'CASE RESULT') else max(f_test(grp, 'AGG')) end as res_agg from a where f_test(grp, 'WHERE') = grp group by grp
GRP | RES_AGG --: | :------ 2 | 2 0 | 0 1 | 1
select * from t order by id
ID | VAL | SRC -: | --: | :------------- 1 | 1 | WHERE 2 | 1 | AGG 3 | 2 | WHERE 4 | 2 | AGG 5 | 0 | WHERE 6 | 0 | AGG 7 | 1 | WHERE 8 | 1 | AGG 9 | 2 | WHERE 10 | 2 | AGG 11 | 0 | WHERE 12 | 0 | AGG 13 | 2 | CASE CONDITION 14 | 2 | CASE RESULT 15 | 0 | CASE CONDITION 16 | 1 | CASE CONDITION 17 | 1 | CASE RESULT
db<;>;小提琴here
但是,您可以像在Oracle 12c+中那样解决此问题。您可以在with
子句中声明本地函数。这样,您可以将数据聚合为集合类型,然后在PL/SQL中将其连接起来。或者作为一种通用且更快速的方法:按照另一个答案中的描述,为clob
数据类型定义您的自定义Listagg。
with function f_listagg_clob( p_vc2_tab in sys.odcivarchar2list , p_sep in varchar2 default ', ' ) return clob as r_clob clob; begin for i in 1..p_vc2_tab.count loop r_clob := r_clob || case when i > 1 then p_sep end || p_vc2_tab(i); end loop; return r_clob; end; a as ( select dbms_random.string('X', 100) as str from dual connect by level < 1000 ) select length(f_listagg_clob(cast(collect(str) as sys.odcivarchar2list))) as result_len from a
| RESULT_LEN | | ---------: | | 101896 |
db<;>;小提琴here
相关文章