Oracle WM_CONCAT与DISTINCT子句-编译包与独立查询问题

Oracle WM_CONCAT与DISTINCT子句-编译包与独立查询问题,oracle,plsql,oracle10g,oracle-sqldeveloper,Oracle,Plsql,Oracle10g,Oracle Sqldeveloper,我在写一些使用WM_CONCAT函数的程序。运行此查询时: SELECT WM_CONCAT(DISTINCT employee_id) FROM employee WHERE ROWNUM < 20; 它很好用。当我试图在包函数或过程中编译相对相同的查询时,它会产生以下错误:PL/SQL:ORA-30482:DISTINCT option not allowed for this function FUNCTION fetch_raw_data_by_range RETURN V

我在写一些使用WM_CONCAT函数的程序。运行此查询时:

SELECT WM_CONCAT(DISTINCT employee_id)
FROM   employee
WHERE  ROWNUM < 20;
它很好用。当我试图在包函数或过程中编译相对相同的查询时,它会产生以下错误:PL/SQL:ORA-30482:DISTINCT option not allowed for this function

FUNCTION fetch_raw_data_by_range
RETURN VARCHAR2 IS

    v_some_string VARCHAR2(32000);

BEGIN

    SELECT WM_CONCAT(DISTINCT employee_id)
    INTO   v_some_string
    FROM   employee
    WHERE  ROWNUM < 20;

    RETURN v_some_string;

END;

我意识到WM_CONCAT没有得到官方支持,但有人能解释一下为什么它可以作为一个独立的查询使用,但不能在包中编译吗?

问题是WM_CONCAT是在pl/sql上编写的存储过程

有一个开放的bug 9323679:PL/SQL调用用户定义的aggregate函数,该函数与ORA-30482不同

解决此类问题的方法是使用动态sql

因此,如果您将查询封装在

EXECUTE IMMEDIATE '<your_query>';
那么它应该会起作用


但是正如OldProgrammer已经建议的那样,您最好避免使用这个WM_CONCAT。

PL/SQL不允许您在聚合函数中使用distinct,这个问题表明SQL引擎和PL/SQL引擎不使用相同的解析器

解决此问题的方法之一是使用子查询,如下所示:

SELECT WM_CONCAT(employee_id)
INTO   v_some_string
FROM   (select DISTINCT employee_id
        FROM   employee)
WHERE  ROWNUM < 20;
另一个解决方案是使用Nagh建议的动态SQL

FUNCTION fetch_raw_data_by_range
RETURN VARCHAR2 IS

    v_some_string VARCHAR2(32000);
    v_sql VARCHAR2(200);

BEGIN

    v_sql :='SELECT WM_CONCAT(DISTINCT employee_id)
             FROM   employee
             WHERE  ROWNUM < 20';

    execute immediate v_sql INTO v_some_string;
    RETURN v_some_string;
END;

您应该能够使用LISTAGG函数获得类似的结果。我将其标记为oracle10g,它不提供该函数。我意识到pl/sql解析器与查询解析器不同,但我真正想知道的是它发生的原因,即导致这种行为的规则是什么。可能有一个很好的理由,在pl/sql的某些特定场景中不允许使用DISTINCT,我这里的示例是其中的一个子集示例,不能代表“问题”的整体。您能提供一个到描述此行为的文档的链接吗?@Reimus抱歉,似乎我有点把这个问题与新的11g行为混淆了。我正在修正这个答案。啊,所以这是一个bug,不是因为一些功能需求。谢谢你的参考资料。我没有权限访问他们的追踪器,但我能够找到更多与bug编号相关的帖子。