10

Oracle 11g r2を使用しており、複数の行の文字列(VARCHAR2、300)を連結する必要があります。私はLISTAGG、連結された文字列が制限に達するまでうまく機能するものを使用しています。その時点で私はを受け取りますORA-01489: result of string concatenation is too long

結局、連結された文字列の最初の4000文字だけが必要です。どうやってそこにたどり着くかは関係ありません。非効率的な解決策を受け入れます。

これが私の質問です:

SELECT LISTAGG(T.NAME, ' ') WITHIN GROUP (ORDER BY NULL)
FROM T
4

4 に答える 4

4

このコードは、あらゆる長さのデータに対して十分な速度で機能します

SELECT REPLACE(
         REPLACE(
           XMLAGG(
             XMLELEMENT("A",T.NAME)
           ORDER BY 1).getClobVal(),
         '<A>',''),
       '</A>','[delimiter]')
FROM T
于 2013-09-26T10:15:28.420 に答える
3

組み込みの(ただし非推奨の)STRAGG関数を使用できます

    select sys.stragg(distinct name) from t

(重複を避けるために別個のものが必要であるように思われることに注意してください)

または、独自の集計関数/タイプを定義します。

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
    -- prevent buffer overflow for more than 4,000 characters
    if nvl(length(self.total),
           0) + nvl(length(value),
                    0) < 4000 then
      self.total := self.total || ';' || value;
    end if;
    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;

次のように使用します。

select STRAGG(name) from t

このアプローチは元々TomKyteによって提案されたと思います(少なくとも、そこから入手しました-Asktom:StringAgg

于 2012-09-07T10:35:47.170 に答える
1

多分それはあなたを助けるでしょう:

substr(string, 1, 4000)

編集:

または試してみてください

SELECT [column], rtrim(
         xmlserialize(content 
           extract(
             xmlagg(xmlelement("n", (T.NAME||',') order by [column])
           , '//text()'
           )
         )
       , ','
       ) as list
FROM [table]
GROUP BY [column]
;
于 2012-09-07T09:26:09.110 に答える
1

これは、LISTAGG関数の欠点であり、LISTAGG分析関数によって生成された文字列の制限を処理しません。そのためには、長さの累積合計を取得し、それに基づいて制限する必要があります。

worked out example on emp table 

select listagg(ename,' ')within group (order by null)
from
(
select ename,
         sum( length( ename ) + 1) 
            over ( order by ename rows between unbounded preceding and current row) length
 from emp

 )where lngth <= 4000
 ;

ただし、内部クエリを見ると、以下に示すようにenameとその長さの列が生成されるため、これでは完全な結果は得られません。

 ename      lenght 
===================
gaurav        6
rohan         11
:
:
garima        3996
anshoo        4002
=====================

したがって、 listaggは内部クエリの長​​さ列に基づいているため、上記の関数は、garimaまでではなく、までの結果を提供します。ansh

于 2012-09-07T10:50:14.203 に答える