ora-01489 字符串連接的結果過長 解決方案


  如下代碼,使用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;

  

  

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM