LISTAGG vs XMLAGG

LISTAGG gives “java.sql.SQLException: ORA-01489: result of string concatenation is too long” due to limitation for VARCHAR2.

select
  CONCAT(CONCAT(t2.REF_NUM_TYPE,':'), (listagg(t2.REF_NUM,',') within group (order by t2.REF_NUM asc))) as REF_NUMS_BK
from
(
	select
		max(s.PIPELINE_TX_ID) as PIPELINE_TX_ID,
		rn.ref_num_type,
		rn.ref_num
	from 
		reference_numbers rn, 
		ouk_shipment_activity_cmpny s 
	where 1=1
	and rn.pipeline_tx_id = s.pipeline_tx_id
	and s.PIPELINE_TX_ID = '123132123123'
	group by
		rn.ref_num_type,
		rn.ref_num
	order by
		rn.ref_num_type,
		rn.ref_num
) t2
where 1=1
group by
  t2.ref_num_type

Therefore, XMLELEMENT can be workaround.

select
  CONCAT(CONCAT(t2.REF_NUM_TYPE,':'),(RTRIM(XMLAGG(XMLELEMENT(e,t2.REF_NUM,',').EXTRACT('//text()')).GetClobVal(),','))) AS REF_NUMS
from
(
	select
		max(s.PIPELINE_TX_ID) as PIPELINE_TX_ID,
		rn.ref_num_type,
		rn.ref_num
	from 
		reference_numbers rn, 
		ouk_shipment_activity_cmpny s 
	where 1=1
	and rn.pipeline_tx_id = s.pipeline_tx_id
	and s.PIPELINE_TX_ID = '123132123123'
	group by
		rn.ref_num_type,
		rn.ref_num
	order by
		rn.ref_num_type,
		rn.ref_num
) t2
where 1=1
group by
  t2.ref_num_type

It can be trim as well.

select
 CONCAT(
  CONCAT(t2.REF_NUM_TYPE,':'),
   SUBSTR(
    (RTRIM(XMLAGG(XMLELEMENT(e,t2.REF_NUM,',').EXTRACT('//text()')).GetClobVal(),',')
   ),1,1000
  )
 ) AS REF_NUMS
from
(
	select
		max(s.PIPELINE_TX_ID) as PIPELINE_TX_ID,
		rn.ref_num_type,
		rn.ref_num
	from 
		reference_numbers rn, 
		ouk_shipment_activity_cmpny s 
	where 1=1
	and rn.pipeline_tx_id = s.pipeline_tx_id
	and s.PIPELINE_TX_ID = '30277174594' -- 202501494 202498201 30277174594(too long)
	group by
		rn.ref_num_type,
		rn.ref_num
	order by
		rn.ref_num_type,
		rn.ref_num
) t2
where 1=1
group by
  t2.ref_num_type

Example for XMLAGG with order by

with ref_base as (
    select 
     max(a.PIPELINE_TX_ID) as ppl
    ,a.REF_NUM_TYPE
    ,a.REF_NUM
    from REFERENCE_NUMBERS a where 1=1
    and a.PIPELINE_TX_ID = '30277174594'
    group by a.REF_NUM_TYPE, a.REF_NUM
    order by a.REF_NUM_TYPE, a.REF_NUM
)
select
(
    select RTRIM((XMLAGG(XMLELEMENT(e, b.REF_NUM,',') order by b.REF_NUM).EXTRACT('//text()')).GetClobVal(),',') AS REF_NUMS
    from   ref_base b where  b.REF_NUM_TYPE = 'ED1'
    group  by b.REF_NUM_TYPE
) as REF_NUMS_ED1
from dual

Example for LISTAGG with limited elements

select
  LISTAGG(
   case
      when rownum <= 300 
      then (
        case
           when rownum = 300
           then rn.ref_num || ' MORE....'
           else rn.ref_num
        end
      )
      else null
   end,
   ','
  ) within group (order by rn.ref_num)
  as ref_nums
from reference_numbers rn
where rn.pipeline_tx_id = '123456'

Leave a Reply

Your email address will not be published. Required fields are marked *

This site uses Akismet to reduce spam. Learn how your comment data is processed.