【问题标题】:alternative to listagg in Oracle?Oracle 中 listagg 的替代品?
【发布时间】:2012-02-23 11:51:56
【问题描述】:

listagg 是Oracle 11.2 中引入的一个函数!现在这个函数正在困扰我们,我们正在从 MySQL 迁移到 Oracle,我们有这个查询:

SELECT
    p_id,
    MAX(registered) AS registered,
    listagg(MESSAGE, ' ') within GROUP (ORDER BY registered) AS MESSAGE
  FROM
    umm_parent_id_remarks_v m
  GROUP BY
    m.p_id;

据我们所知,在 MySQL 中运行良好 在 Oracle 下困扰我们的是它返回 VARCAR 而不是我们需要的 CLOB! 文本很大,我们确实需要它是 CLOB

这是我尝试做的!

创建一个CLOB类型的CLOB_T表!

然后创建函数

create or replace
function listaggclob (t in clob_t) 
  return clob
as 
  ret clob := '';
  i   number;
begin
  i := t.first;
  while i is not null loop
    if ret is not null then
      ret := ret || ' ';
    end if;
    ret := ret || t(i);
    i := t.next(i);
  end loop;
  return ret;
end;

现在如果我运行它:

  SELECT
        p_id,
        MAX(registered) AS registered,
        listaggclob(cast(collect (MESSAGE) as clob_t)) MESSAGE
      FROM
        umm_parent_id_remarks_v m
      GROUP BY
        m.p_id;

我明白了

ORA-22814:属性或元素值大于类型中指定的值

有什么解决办法吗?

谢谢你

【问题讨论】:

    标签: sql oracle varchar clob


    【解决方案1】:

    【讨论】:

    • 我确实编写了自己的函数并更新了我的问题,请再次查看我的问题,谢谢
    • 我不知道您为什么会收到该错误 - 不过可能值得将其作为一个新问题发布,您会吸引更多人关注它。
    【解决方案2】:

    WM_CONCAT 为我工作。

    SELECT replace(WMSYS.WM_CONCAT(myTable.name), ',', ';')
    FROM myTable
    GROUP BY myTable.id
    

    我用“替换”将其包装起来,以指定与 WM_CONCAT (',') 使用的不同的项目分隔符 (';')。

    【讨论】:

    • 请注意,WM_CONCAT 在 12c、Express Edition 以及任何未安装 Workspace Manager 的数据库中均不可用。
    • 现在不支持也不记录
    【解决方案3】:

    您可以通过使用MULTISET 而不是COLLECT 来解决ORA-22814 错误:

    SELECT
        p_id,
        MAX(registered) AS registered,
        listaggclob(cast(multiset(
            select MESSAGE
            from umm_parent_id_remarks_v
            where umm_parent_id_remarks_v.p_id = m.p_id
        ) as clob_t)) MESSAGE
      FROM
        umm_parent_id_remarks_v m
      GROUP BY
        m.p_id;
    

    【讨论】:

      【解决方案4】:

      你可能想看看user-defined aggregate functions

      here 显示了不同的字符串聚合技术。它们包括用户定义的聚合函数的示例。

      【讨论】:

      • 那里有很好的选择。有什么更快的信息吗?
      • 我没有任何关于性能的信息。我想这主要取决于整体执行计划以及它们如何适应该执行计划。所以它可能因查询而异。
      【解决方案5】:

      使用xmlAgg,示例如下:

      SELECT RTRIM(XMLAGG(XMLELEMENT(E,colname,',').EXTRACT('//text()') ORDER BY colname).GetClobVal(),',') AS LIST
      FROM tablename;
      

      这将返回 clob 值,因此无需创建自定义函数。

      【讨论】:

      • XMLAGG 很慢。
      • 有什么快速的替代方案吗?
      【解决方案6】:

      -- 创建 Clob 类型 -- 创建或替换类型“MSCONCATIMPL_CLOB”作为对象( 结果字符串 CLOB, 分隔符 VARCHAR2(10),

      STATIC FUNCTION odciaggregateinitialize ( io_srccontext IN OUT msconcatimpl_clob ) RETURN NUMBER,
      
      MEMBER FUNCTION odciaggregateiterate (
          self IN OUT msconcatimpl_clob,
          value   IN CLOB
      ) RETURN NUMBER,
      
      MEMBER FUNCTION odciaggregateterminate (
          self            IN msconcatimpl_clob,
          o_returnvalue   OUT CLOB,
          i_flags         IN NUMBER
      ) RETURN NUMBER,
      
      MEMBER FUNCTION odciaggregatemerge (
          self IN OUT msconcatimpl_clob,
          i_ctx2   IN msconcatimpl_clob
      ) RETURN NUMBER
      

      ); / -- 创建 Clobe 类型体 --

      创建或替换类型主体“MSCONCATIMPL_CLOB”是 静态函数 odciaggregateinitialize (io_srccontext IN OUT msconcatimpl_clob) 返回编号 是 开始 io_srccontext := msconcatimpl_clob( 空值, 空值 ); io_srccontext.delimiter := ' '; 返回 odciconst.success; END odciaggregateinitialize;

      MEMBER FUNCTION odciaggregateiterate (
          self IN OUT msconcatimpl_clob,
          value   IN CLOB
      ) RETURN NUMBER
          IS
      BEGIN
          IF
              value IS NOT NULL
          THEN
              IF
                  self.resultstring IS NULL
              THEN
                  self.resultstring := self.resultstring || value;
              ELSE
                  self.resultstring := self.resultstring
                   || self.delimiter
                   || value;
              END IF;
          END IF;
      
          RETURN odciconst.success;
      END odciaggregateiterate;
      
      MEMBER FUNCTION odciaggregateterminate (
          self            IN msconcatimpl_clob,
          o_returnvalue   OUT CLOB,
          i_flags         IN NUMBER
      ) RETURN NUMBER
          IS
      BEGIN
          o_returnvalue := self.resultstring;
          RETURN odciconst.success;
      END odciaggregateterminate;
      
      MEMBER FUNCTION odciaggregatemerge (
          self IN OUT msconcatimpl_clob,
          i_ctx2   IN msconcatimpl_clob
      ) RETURN NUMBER
          IS
      BEGIN
          IF
                  self.resultstring IS NULL
              AND
                  i_ctx2.resultstring IS NOT NULL
          THEN
              self.resultstring := i_ctx2.resultstring;
          ELSIF
              self.resultstring IS NOT NULL
          AND
              i_ctx2.resultstring IS NOT NULL
          THEN
              self.resultstring := self.resultstring
               || self.delimiter
               || i_ctx2.resultstring;
          END IF;
      
          RETURN odciconst.success;
      END odciaggregatemerge;
      

      结束; /

      -- 创建 Clobe 函数--

      创建或替换函数 ms_concat_clob (输入 VARCHAR2) 返回 CLOB PARALLEL_ENABLE 使用 msconcatimpl_clob 聚合; /

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2020-01-14
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2019-12-19
        • 2021-07-25
        相关资源
        最近更新 更多