5

我有这个查询:

(SELECT OBJECT_ID from cr_object_group_entries_vw where object_group_id IN
    (SELECT ITEM FROM TABLE(CR_FN_SPLIT_STRING('28,56',','))))

返回:

在此处输入图像描述

但是当我这样做时:

SELECT wm_concat(object_id) FROM
    (SELECT OBJECT_ID from cr_object_group_entries_vw where object_group_id IN
        (SELECT ITEM FROM TABLE(CR_FN_SPLIT_STRING('28,56',','))))

我得到一个空白的结果......我做错了什么?

4

4 回答 4

8

您必须避免wm_concat使用函数,因为它在 Oracle 8i 时代没有被记录并作为解决方法被发现。

由于 Tom Kyte在这里发现了具有自定义聚合函数的旧方法,因此有一些新的解决方法,如下面的示例所示。

所有这些都在这个 SQL Fiddle中重现。

解决方法 1 - LISTAGG 函数,适用于 11g:

select listagg(object_id,',') within group (order by rownum) id_string
from cr_object_group_entries_vw

解决方法 2 - SYS_CONNECT_BY_PATH,从 10g 开始工作:

select id_string from (
  select rn, substr(sys_connect_by_path(object_id, ','),2) id_string
  from (select object_id, rownum rn from cr_object_group_entries_vw)
  start with rn = 1
  connect by prior rn + 1 = rn
  order by rn desc
)
where rownum = 1

解决方法 3 - XMLAGG,从 10g 开始工作:

select replace(
         replace(
           replace(
             xmlagg(xmlelement("x",object_id)).getStringVal(),
             '</x><x>',
             ','
           ),
           '<x>',
           ''
         ),
         '</x>',
         ''
       ) id_string
from cr_object_group_entries_vw

PS 我不知道具体是在哪个 Oracle 版本sys_connect_by_pathxmlagg引入的,但两者都在 10.2.0.4.0 上运行良好

于 2013-05-21T17:25:08.633 回答
5

如果您使用的是 11g,请尝试LISTAGG而不是wm_concat初学者。

于 2013-05-21T16:41:48.283 回答
3

我刚刚看到这篇关于wm_concat并想分享一些信息的帖子。

任何一直依赖wm_concat功能的应用程序一旦升级到12c. 从那以后,它已从最新的 12c 版本中删除。请参阅为什么不在 Oracle 中使用 WM_CONCAT 函数?

SQL> select banner from v$version where rownum = 1;

BANNER
----------------------------------------------------------------------------
Oracle Database 12c Enterprise Edition Release 12.1.0.1.0 - 64bit Production

SQL> SELECT object_name
  2  FROM dba_objects
  3  WHERE owner='WMSYS'
  4  AND object_name LIKE 'WM\_%' ESCAPE '\';

OBJECT_NAME
----------------------------------------------------------------------------
WM_REPLICATION_INFO
WM_RDIFF
WM_PERIOD
WM_PERIOD
WM_OVERLAPS
WM_MEETS
WM_LESSTHAN
WM_LDIFF
WM_INTERSECTION
WM_INSTALLATION
WM_GREATERTHAN
WM_EVENTS_INFO
WM_ERROR
WM_ERROR
WM_EQUALS
WM_DDL_UTIL
WM_DDL_UTIL
WM_CONTAINS
WM_COMPRESS_BATCH_SIZES
WM_COMPRESSIBLE_TABLES

20 rows selected.

您将收到“<strong>invalid identifier”错误:

SQL> SELECT banner FROM v$version;

BANNER
----------------------------------------------------------------------------
Oracle Database 12c Enterprise Edition Release 12.1.0.1.0 - 64bit Production
PL/SQL Release 12.1.0.1.0 - Production
CORE    12.1.0.1.0      Production
TNS for 64-bit Windows: Version 12.1.0.1.0 - Production
NLSRTL Version 12.1.0.1.0 - Production

SQL> SELECT deptno, wm_concat(ename) FROM emp;
SELECT deptno, wm_concat(ename) FROM emp
               *
ERROR at line 1:
ORA-00904: "WM_CONCAT": invalid identifier

因此,没有必要依赖最新版本中不再提供的未记录功能。

有关替代解决方案,请参阅Oracle 字符串聚合技术

于 2015-02-27T05:26:03.353 回答
2

你似乎没有做错什么。使用虚拟表函数返回您显示的数据,wm_concat对我有用:

select wm_concat(object_id) from
    (select object_id from cr_object_group_entries_vw where object_group_id in
        (select item from table(cr_fn_split_string('28,56',','))))
/

WM_CONCAT(OBJECT_ID)                                                           
--------------------------------------------------------------------------------
36,1,11,121,13,14,17,18,2,24,3,32,33,34,35,36,37,38,39,40,42,43,44,6,7,8,81      

您已将问题标记为 [11g];正如@beherenow 所说,如果可以的话,您应该使用 supportedlisgagg而非 unsupported wm_concat,尽管我认为它仅适用于 11gR2:

select listagg(object_id, ',') within group (order by object_id)
from cr_object_group_entries_vw
where object_group_id in
    (select item from table(cr_fn_split_string('28,56',',')))
/

LISTAGG(OBJECT_ID,',')WITHINGROUP(ORDERBYOBJECT_ID)
---------------------------------------------------------------------------
1,11,121,13,14,17,18,2,24,3,32,33,34,35,36,36,37,38,39,40,42,43,44,6,7,8,81

SQL Fiddlelistagg仅限,因为它不支持wm_concat- 也许您的实例也不支持,但它应该出错?)

于 2013-05-21T17:21:50.180 回答