【问题标题】:how to fix wm_concat in oracle 12c如何在 oracle 12c 中修复 wm_concat
【发布时间】:2019-07-01 10:55:17
【问题描述】:

由于 wm_concat 在 oracle 12C 中已弃用,我需要修改以下查询,我尝试使用 LISTAGG 但它不起作用

SELECT WM_CONCAT(CLRR.CLNTNUM)
    || '#'
    ||WM_CONCAT(trim(trim(clnt.salutl)
    || ' '
    || trim(clnt.lgivname)
    || ' '
    || trim(clnt.lsurname)))
  FROM ODSLIFEASIA.CLRRPF CLRR,
    odslifeasia.clntpf clnt
  WHERE clnt.clntnum             = CLRR.CLNTNUM
  AND CLRRROLE                   = 'LF'
  AND clnt.validflag            IN ('1', '3')
  AND NVL(USED2B, 'X')          <> 'U'
  AND rownum                     <5;

我尝试了下面的代码,但它不起作用:

SELECT LISTAGG(CLRR.CLNTNUM,',') within group (order by CLRR.CLNTNUM)--WM_CONCAT(CLRR.CLNTNUM)
        || '#'
        ||LISTAGG(trim(trim(clnt.salutl,',') within group (order by CLRR.clnt.salutl)--WM_CONCAT(trim(trim(clnt.salutl)
        || ' '
        || trim(clnt.lgivname)
        || ' '
        || trim(clnt.lsurname)))
      FROM ODSLIFEASIA.CLRRPF CLRR,
        odslifeasia.clntpf clnt
      WHERE clnt.clntnum             = CLRR.CLNTNUM
      AND CLRRROLE                   = 'LF'
      AND clnt.validflag            IN ('1', '3')
      AND NVL(USED2B, 'X')          <> 'U'
      AND rownum                     <5;

我尝试了下面的代码,但它不起作用:

    SELECT LISTAGG(CLRR.CLNTNUM,',') within group (order by CLRR.CLNTNUM)--WM_CONCAT(CLRR.CLNTNUM)
    || '#'
    ||LISTAGG(trim(trim(clnt.salutl,',') within group (order by CLRR.clnt.salutl)--WM_CONCAT(trim(trim(clnt.salutl)
    || ' '
    || trim(clnt.lgivname)
    || ' '
    || trim(clnt.lsurname)))
  FROM ODSLIFEASIA.CLRRPF CLRR,
    odslifeasia.clntpf clnt
  WHERE clnt.clntnum             = CLRR.CLNTNUM
  AND CLRRROLE                   = 'LF'
  AND clnt.validflag            IN ('1', '3')
  AND NVL(USED2B, 'X')          <> 'U'
  AND rownum                     <5;

我无法使用LISTAGG 获得输出,但使用wm_concat 我得到了:

53155087,53155088,53155089,53155090#MR IONE 包销,MR IONE 包销,MR IONE 包销,MR IONE 包销

和我期待的一样

【问题讨论】:

  • 很少有人能够在不运行一些 SQL 的情况下为您提供帮助,因此您可能需要在您的问题中添加一些示例数据。
  • “没用”是什么意思?您是否收到一些错误代码,或者没有按您的意愿返回?顺便说一句,由于trim(clnt.lsurname))) 末尾的括号很重,并且第三行末尾缺少括号,查询似乎有错字。
  • 另外order by CLRR.clnt.salutl(在第二个 LISTAGG 中)不代表任何列。应该是order by clnt.salutl
  • “它不起作用”没有帮助。我们无权访问您的数据,看不到您屏幕上的内容,也不知道“它不起作用”是什么意思。请使用edit 按钮编辑您的问题,并解释您的每个示例查询“它不起作用”的含义。谢谢。

标签: sql oracle string-aggregation


【解决方案1】:

首先连接值salut1、lgivname 和lsurname,然后使用listagg()。应该是:

select listagg(clrr.clntnum,',') 
           within group (order by clrr.clntnum) || '#' ||
       listagg(trim(trim(clnt.salutl)|| ' '|| 
                    trim(clnt.lgivname)|| ' ' || 
                    trim(clnt.lsurname)), ',')
           within group (order by clnt.salutl)
      from odslifeasia.clrrpf clrr
      join odslifeasia.clntpf clnt on clnt.clntnum = clrr.clntnum
      where clrrrole           = 'LF'
        and clnt.validflag     in ('1', '3')
        and nvl(used2b, 'x')   <> 'U'
        and rownum             < 5;

我希望我没有打错字。也可以使用join

顺便说一句:您对两个列表使用不同的顺序,也许使用相同的顺序会更好?

【讨论】:

  • 是的,wm_concat() 函数在 Oracle 11 中有效,在 Oracle 12 中被替换为 listagg()。
  • @Tomasz 一些小的更正 - LISTAGG 是在 11.2 中引入的。它并没有真正取代WM_CONCATWM_CONCAT 未被弃用,它是一个内部的、不受支持的功能,我们不应该使用它。
【解决方案2】:

整齐地格式化您的查询将帮助您了解函数参数的位置。

LISTAGG 语法是:

LISTAGG( value, separator ) WITHIN GROUP ( ORDER BY columns )

这里,value 是称呼、名字和姓氏的串联,然后应该是 separator 字符串。您将括号放在错误的位置,因此 LISTAGG 函数的分隔符参数位于 TRIM 函数内。

SELECT LISTAGG(
         CLRR.CLNTNUM,
         ','
       ) WITHIN GROUP (ORDER BY CLRR.CLNTNUM)
       || '#'
       || LISTAGG(
            trim(
              trim(clnt.salutl)
              || ' '
              || trim(clnt.lgivname)
              || ' '
              || trim(clnt.lsurname)
            ),
            ','
          ) WITHIN GROUP (ORDER BY CLRR.clnt.salutl)
FROM   ODSLIFEASIA.CLRRPF CLRR
       INNER JOIN odslifeasia.clntpf clnt
       ON ( clnt.clntnum = CLRR.CLNTNUM)
WHERE CLRRROLE                   = 'LF'
AND   clnt.validflag            IN ('1', '3')
AND   NVL(USED2B, 'X')          <> 'U'
AND   rownum                    <5;

【讨论】:

    【解决方案3】:

    WM_CONCAT 尚未被弃用,它已被删除。它是数据库中不受支持且未记录的功能(即使它是 WMSYS 架构 [工作区管理器] 的一部分,但未记录)。因此,它是供 Oracle 内部使用的功能,这意味着它可以随时删除,恕不另行通知。

    正如其他人所报告的,listagg() 仍然可用,并且是从 11.2 开始的各种 oracle 版本中受支持的函数。让我们看一个使用 EMP 表的工作示例:

    `SQL> select listagg(empno, ',') within group (order by empno) emplist from emp 2 /

    EMPLIST

    7369,7499,7521,7566,7654,7698,7782,7788,7839,7844,7876,7900,7902,7934

    SQL>`

    获取部门列表:

    `SQL) > select deptno, listagg(empno, ',') within group (order by empno) emplist from emp 2 按部门编号分组 3 /

    DEPTNO E0MPLIST
    

        10 7782,7839,7934
        20 7369,7566,7788,7876,7902
        30 7499,7521,7654,7698,7844,7900
    

    SQL>`

    希望这会有所帮助。

    【讨论】:

      【解决方案4】:

      您可以创建自己的用户定义聚合函数,如下所述:https://asktom.oracle.com/pls/apex/f?p=100:11:0::::P11_QUESTION_ID:2196162600402

      这是代码:

      CREATE OR REPLACE TYPE BigStringConcat 
      AS OBJECT
      (
          runningStr      CLOB,
          
          STATIC FUNCTION ODCIAggregateInitialize (actx IN OUT BigStringConcat)
              RETURN NUMBER,
              
          MEMBER FUNCTION ODCIAggregateIterate (
                                                  self   IN OUT BigStringConcat,
                                                  value  IN     VARCHAR2)
              RETURN NUMBER,
              
          MEMBER FUNCTION ODCIAggregateTerminate (
                                                  self          IN     BigStringConcat,
                                                  returnValue   OUT    CLOB,
                                                  flags         IN     NUMBER)
              RETURN NUMBER,
              
          MEMBER FUNCTION ODCIAggregateMerge (self   IN OUT BigStringConcat,
                                              ctx2   IN     BigStringConcat)
              RETURN NUMBER
      );
      /
      
      CREATE OR REPLACE TYPE BODY BigStringConcat 
      AS     
          STATIC FUNCTION ODCIAggregateInitialize (actx IN OUT BigStringConcat)
              RETURN NUMBER
          IS 
          BEGIN
              actx := BigStringConcat(EMPTY_CLOB());
              RETURN ODCIConst.Success;
          END;
              
          MEMBER FUNCTION ODCIAggregateIterate (
                                                  self   IN OUT BigStringConcat,
                                                  value  IN     VARCHAR2)
              RETURN NUMBER
          IS
          BEGIN
              self.runningStr := self.runningStr || value || ',';
              RETURN ODCIConst.Success;
          END;    
              
          MEMBER FUNCTION ODCIAggregateTerminate (
                                                  self          IN     BigStringConcat,
                                                  returnValue   OUT    CLOB,
                                                  flags         IN     NUMBER)
              RETURN NUMBER
          IS
          BEGIN
              returnValue := RTRIM(self.runningStr, ',');
              RETURN ODCIConst.Success;
          END;
              
          MEMBER FUNCTION ODCIAggregateMerge (self   IN OUT BigStringConcat,
                                              ctx2   IN     BigStringConcat)
              RETURN NUMBER
          IS
          BEGIN
              self.runningStr := self.runningStr || ctx2.runningStr;
              RETURN ODCIConst.Success;
          END;
      
      
      END;
      /
      
      CREATE or replace FUNCTION cn_concat (INPUT VARCHAR2) RETURN CLOB
      PARALLEL_ENABLE AGGREGATE USING BigStringConcat;
      
      SQL> SELECT LENGTH(CN_CONCAT(object_name))
      2  FROM all_objects;
      
      LENGTH(CN_CONCAT(OBJECT_NAME))
      ------------------------------
                             1251401
      
      Elapsed: 00:00:03.04
      

      在 Oracle Database 19c 企业版 19.0.0.0.0 版上测试。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2010-12-30
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2016-08-07
        • 1970-01-01
        相关资源
        最近更新 更多