如何在Oracle 12c中修复wm_concat

时间:2019-07-01 10:55:17

标签: sql oracle string-aggregation

由于在Oracle 12C中不推荐使用wm_concat,因此我需要修改以下查询,我尝试使用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承保

我期望的一样

4 个答案:

答案 0 :(得分:3)

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

chart.setOnChartValueSelectedListener(this)

override fun onNothingSelected() {
    Log.i("Entry selected", "Nothing selected.")
}

override fun onValueSelected(e: Entry?, h: Highlight?) {
    Log.i("Entry selected", e.toString())
    val x:Float =e!!.x
    val y:Float =e!!.y
    chart.highlightValue(h)

}

我希望我没有打错字。还要使用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;

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

答案 1 :(得分:1)

整齐地设置查询格式将有助于您了解函数参数应该在哪里。

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;

答案 2 :(得分:1)

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

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

`SQL>从emp中选择组(按empno排序)emplist中的listagg(empno,',') 2 /

EMPLIST

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

SQL>`

要获取部门列表:

`SQL)>从emp中选择组(按empno排序)emplist中的deptno,listagg(empno,',') 2组按deptno 3 /

DEPTNO E0MPLIST

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

SQL>`

希望这会有所帮助。

答案 3 :(得分:0)

您可以按照以下说明创建自己的用户定义的聚合函数: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版上进行了测试。