Skip to Main Content

Breadcrumb

Question and Answer

Connor McDonald

Thanks for the question, krishna.

Asked: January 24, 2016 - 6:07 pm UTC

Last updated: January 25, 2016 - 10:27 am UTC

Version: 11g

Viewed 10K+ times! This question is

You Asked

Hi,

I am facing ora-01489 result of string concatenation is too long during the usage of LISTAGG function in oracle 11g R2.
So, have taken code from below url and created type, type body (string_agg_type) and one function stragg.

url
https://asktom.oracle.com/pls/apex/f?p=100:11:0%3a%3a%3a%3aP11_QUESTION_ID:2196162600402#29842804516386

code
create or replace type string_agg_type as object
(
total varchar2(4000),

static function
ODCIAggregateInitialize(sctx IN OUT string_agg_type )
return number,

member function
ODCIAggregateIterate(self IN OUT string_agg_type ,
value IN varchar2 )
return number,

member function
ODCIAggregateTerminate(self IN string_agg_type,
returnValue OUT varchar2,
flags IN number)
return number,

member function
ODCIAggregateMerge(self IN OUT string_agg_type,
ctx2 IN string_agg_type)
return number
);

create or replace type body string_agg_type
is

static function ODCIAggregateInitialize(sctx IN OUT string_agg_type)
return number
is
begin
sctx := string_agg_type( null );
return ODCIConst.Success;
end;

member function ODCIAggregateIterate(self IN OUT string_agg_type,
value IN varchar2 )
return number
is
begin
self.total := self.total || ',' || value;
return ODCIConst.Success;
end;

member function ODCIAggregateTerminate(self IN string_agg_type,
returnValue OUT varchar2,
flags IN number)
return number
is
begin
returnValue := ltrim(self.total,',');
return ODCIConst.Success;
end;

member function ODCIAggregateMerge(self IN OUT string_agg_type,
ctx2 IN string_agg_type)
return number
is
begin
self.total := self.total || ctx2.total;
return ODCIConst.Success;
end;
end;

CREATE or replace
FUNCTION stragg(input varchar2 )
RETURN varchar2
PARALLEL_ENABLE AGGREGATE USING string_agg_type;

However, still facing different problem like ORA-06502:PL/SQL:numeric or value error: character string buffer too small. ORA-06512: at "SCOTT.STRING_AGG_TYPE",line 17.

Could you please let me know what changes I have to make in the code.

Regards,
Krishna

and Connor said...

Rating

  (1 rating)

Is this answer out of date? If it is, please let us know via a Comment

Comments

Alternatives

Stew Ashton, January 25, 2016 - 9:03 am UTC

If you really want a VARCHAR2, you are limited to 4000 bytes. You can tell LISTAGG() to stop before it gets over the limit:
drop table t purge;

create table t as
select rpad(to_char(level,'fm09'),level+1,to_char(level,'fm09')) str
from dual
connect by level <= 99;

select listagg(str,',') within group (order by str) big_str
from (
  select str,
  sum(length(str)) over(order by str) +
  row_number() over(order by str)
  - 1 total_length
  from t
)
where total_length <= 4000;

If you really want everything, you have to return a CLOB. You can do that with XML type functions:
select
SUBSTR(
  xmlcast(
    xmlagg(
      xmlelement(s, ',' || str)
      order by str
    ) AS CLOB
  ), 2
) big_str
from t;

Best regards, Stew
Connor McDonald
January 25, 2016 - 10:27 am UTC

Thanks Stew. Some other workarounds are available at:

https://blogs.oracle.com/datawarehousing/entry/managing_overflows_in_listagg

More to Explore

PL/SQL demos

Check out more PL/SQL tutorials on our LiveSQL tool.

PL/SQL docs

PL/SQL reference manual from the Oracle documentation library