Почему здесь не работает wm_concat?

У меня такой запрос:

(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',','))))

У меня пустой результат ... что я делаю не так?


person sprocket12    schedule 21.05.2013    source источник


Ответы (4)


Вы должны избегать wm_concat функции, потому что она недокументирована и обнаружена как временное решение в Oracle 8i раз.

Со времен старого метода с настраиваемой агрегатной функцией, обнаруженного Томом Кайтом здесь есть несколько новых обходных путей, показанных в примерах ниже.

Все они воспроизведены в этом скрипте SQL.

Обходной путь 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

P.S. Я не знал точно, в каких версиях Oracle были представлены версии sys_connect_by_path и xmlagg, но обе хорошо работают на 10.2.0.4.0.

person ThinkJet    schedule 21.05.2013
comment
wm_concat больше не входит в состав `12c. - person Lalit Kumar B; 27.02.2015

Если вы используете 11g, попробуйте LISTAGG вместо wm_concat для начала.

person Kirill Leontev    schedule 21.05.2013

Я только что увидел этот пост о wm_concat и подумал поделиться некоторой информацией.

Любое приложение, которое полагалось на функцию wm_concat, не будет работать после обновления до 12c. С тех пор он был удален из последней версии 12c. См. Почему бы не использовать WM_CONCAT работать в Oracle?

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.

Вы получите сообщение об ошибке «неверный идентификатор»:

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

person Lalit Kumar B    schedule 27.02.2015

Похоже, вы не делаете ничего плохого. С помощью фиктивной табличной функции для возврата данных, которые вы показали, 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, если вы можете, вы должны использовать поддерживаемый lisgagg вместо неподдерживаемого 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 Fiddle (только для listagg, поскольку он не поддерживает wm_concat - возможно, ваш экземпляр тоже не работает, но тогда он должен ошибаться?)

person Alex Poole    schedule 21.05.2013
comment
К сожалению, LISTAGG дает такой же результат, я просто забыл об этом упомянуть. wm_concat также работает для меня при использовании фиктивных данных, но на реальных данных выше LIST AGG и wm_concat не работают. - person sprocket12; 22.05.2013
comment
@MuhammadA - интересно. Похоже, что что-то в вашей табличной функции сбивает с толку или, что более вероятно (возможно), на ваш взгляд, хотя я не могу сразу понять, как это сделать. Можете ли вы увидеть тот же эффект, если замените представление (я предполагаю, что cr_object_group_entries - это представление из имени) базовыми таблицами? - person Alex Poole; 22.05.2013
comment
Я пробовал это - SELECT wm_concat (item) FROM (SELECT * FROM TABLE (CR_FN_SPLIT_STRING ('1,2,12,3,4,12,3', ','))), который сначала разделяется, а затем присоединяется к тому же списку и он работает нормально, но с представлением это не так, хотя когда я просто запускаю подзапрос представления (снимок экрана выше), он возвращает результат, который, как вы могли предположить, позже может быть присоединен. - person sprocket12; 22.05.2013
comment
@MuhammadA - не имея возможности воспроизвести эффект, трудно дать какой-либо дополнительный совет. Единственное, что приходит в голову, это добавить подсказку `/ * + MATERIALIZE * / к выделению из представления, но немного цепляясь за соломинку. Для меня это звучит как ошибка, может, вам лучше поднять SR с Oracle? - person Alex Poole; 22.05.2013