如下代碼,使用listagg進行分組拼接時,常常會報 ora-01489 錯誤,造成該報錯的主要原因是:oracle對字符變量的長度限制,正常情況下,oracle定義的varchar2類型變量的長度不應超過4000字節,如有必要可轉換為long 或clob類型。
我之前遇到一次該報錯,后來檢查了下,是因為重復數據造成的,所以建議大家使用下面方法之前最好還是先看下數據。本文提供的所有方法總結於 ora-01489錯誤解決方案。
create table lu_meseno_temp as select MDSENO, LISTAGG(to_char(MECODE), ',') WITHIN GROUP(ORDER BY MECODE) AS pjMECODE from lu_yb_sbda_md_temp group by MDSENO
解決方案:
方法一:自定義連接函數
-- 定義 tab_varchar2 數據類型 CREATE TYPE tab_varchar2 AS TABLE OF VARCHAR2(4000); -- 新建 concat_array 函數 CREATE OR REPLACE FUNCTION concat_array(p tab_varchar2) RETURN CLOB IS l_result CLOB; BEGIN FOR cc IN (SELECT column_value FROM TABLE(p) ORDER BY column_value) LOOP l_result := l_result ||' '|| cc.column_value; END LOOP; return l_result; END; -- 分組拼接 SELECT item, concat_array(CAST(COLLECT(attribute) AS tab_varchar2)) attributes FROM tb GROUP BY item;
如果希望對上述結果進行排序,可以嵌套一層 order by 前4000字符。
SELECT * FROM ( SELECT item, concat_array(CAST(collect(attribute) AS tab_varchar2)) attributes FROM tb GROUP BY item ) order by -- 表示截取長度4000,起始位置1 dbms_lob.substr(attributes, 4000, 1);
方法二:
with ItemAttribute as ( select 'name'||level name, mod(level,3) itemid from dual connect by level < 2000 ), ItemAttributeGrouped as ( select xmlagg(xmlparse(content name||' ' wellformed) order by name).getclobval() attributes, itemid from ItemAttribute group by itemid ) select itemid, attributes, dbms_lob.substr(attributes,4000,1) sortkey from ItemAttributeGrouped order by dbms_lob.substr(attributes,4000,1);
文檔 oracle listagg函數字符串鏈接的結果過長,給出的解決方案為:
rtrim(xmlagg(XMLELEMENT(e, t.id, ',').EXTRACT('//text()')).getclobval(),',')
其他方法:
SELECT itemId, name FROM ( SELECT itemId, name, min(dr) over (partition by itemId) as dr FROM ( SELECT itemId, name, dense_rank() over (order by name, name1, name2, name3, name4) as dr FROM ( SELECT Item.itemId, Attribute.name, LEAD(Attribute.name, 1) OVER (PARTITION BY Item.itemId ORDER BY Attribute.name) AS name1, LEAD(Attribute.name, 2) OVER (PARTITION BY Item.itemId ORDER BY Attribute.name) AS name2, LEAD(Attribute.name, 3) OVER (PARTITION BY Item.itemId ORDER BY Attribute.name) AS name3, LEAD(Attribute.name, 4) OVER (PARTITION BY Item.itemId ORDER BY Attribute.name) AS name4 FROM Item JOIN ItemAttribute ON ItemAttribute.itemId = Item.itemId JOIN Attribute ON Attribute.attributeId = ItemAttribute.attributeId ) ) ) ORDER BY dr, name;