简体   繁体   English

Listagg溢出功能实现(Oracle SQL)

[英]Listagg Overflow function implementation (Oracle SQL)

I am using LISTAGG function for my query, however, it returned an ORA-01489: result of string concatenation is too long error. 我正在使用LISTAGG函数进行查询,但是返回了ORA-01489: result of string concatenation is too long错误。 So I googled that error and found out I can use ON OVERFLOW TRUNCATE and I implemented that into my SQL but now it generates missing right parenthesis error and I can't seem to figure out why? 因此,我搜索了该错误,发现可以在ON OVERFLOW TRUNCATE使用,并在SQL中实现了该功能,但是现在它会生成missing right parenthesis错误,我似乎无法弄清楚为什么?


My query 我的查询

SELECT DISTINCT cust_id, acct_no, state, language_indicator, billing_system, market_code,
EMAIL_ADDR, DATE_OF_CHANGE, TO_CHAR(DATE_LOADED, 'DD-MM-YYYY') DATE_LOADED, 
(SELECT LISTAGG( SUBSTR(mtn, 7, 4),'<br>' ON OVERFLOW TRUNCATE '***' )
WITHIN GROUP (ORDER BY cust_id || acct_no) mtnlist
FROM process.feature WHERE date_loaded BETWEEN TO_DATE('02-08-2018','MM-dd-yyyy')
AND TO_DATE('02-09-2018', 'MM-dd-yyyy') AND cust_id = ffsr.cust_id
AND acct_no = ffsr.acct_no AND filename = 'FEATURE.VB2B.201802090040'
GROUP BY cust_id||acct_no) mtnlist
FROM process.feature ffsr WHERE date_loaded BETWEEN TO_DATE('02-08-2018','MM-dd-yyyy')
AND TO_DATE('02-09-2018','MM-dd-yyyy') AND cust_id BETWEEN 0542185146 AND 0942025571
AND src_ind = 'B' AND filename = 'FEATURE.VB2B.201802090040'
AND letter_type = 'FA' ORDER BY cust_id;

With a little bit of help by XML, you might get it work. 在XML的帮助下,您可能会使其工作。 Example is based on HR schema. 示例基于HR模式。

SQL> select
  2    listagg(s.department_name, ',') within group (order by null) result
  3  from departments s, departments d;
from departments s, departments d
     *
ERROR at line 3:
ORA-01489: result of string concatenation is too long


SQL>
SQL> select
  2  rtrim(xmlagg(xmlelement (e, s.department_name || ',')).extract
  3    ('//text()').getclobval(), ',') result
  4  from departments s, departments d;

RESULT
--------------------------------------------------------------------------------
Administration,Administration,Administration,Administration,Administration,Admin

SQL>

This demo sourced from livesql.oracle.com 该演示源于livesql.oracle.com

-- Create table with 93 strings of different lengths, plus one NULL string. Notice the only ASCII character not used is '!', so I will use it as a delimiter in LISTAGG.
create table strings as 
with letters as ( 
  select level num, 
  chr(ascii('!')+level) let 
  from dual 
  connect by level <= 126 - ascii('!') 
  union all 
  select 1, null from dual 
) 
select rpad(let,num,let) str from letters;

-- Note the use of LENGTHB to get the length in bytes, not characters.
  select str,   
  sum(lengthb(str)+1) over(order by str rows unbounded preceding) - 1 cumul_lengthb,   
  sum(lengthb(str)+1) over() - 1 total_lengthb,   
  count(*) over() num_values   
  from strings   
  where str is not null;

-- This statement implements the ON OVERFLOW TRUNCATE WITH COUNT option of LISTAGG in 12.2. If there is no overflow, the result is the same as a normal LISTAGG.
select listagg(str, '!') within group(order by str) || 
  case when max(total_lengthb) > 4000 then 
    '! ... (' || (max(num_values) - count(*)) || ')' 
  end str_list 
from ( 
  select str, 
  sum(lengthb(str)+1) over(order by str) - 1 cumul_lengthb, 
  sum(lengthb(str)+1) over() - 1 total_lengthb, 
  count(*) over() num_values 
  from strings 
  where str is not null 
) 
where total_lengthb <= 4000 
   or cumul_lengthb <= 4000 - length('! ... (' || num_values || ')');

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM