Почему 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',','))))
Я получаю пустой результат... что я делаю не так?
4 ответа
Вы должны избегать wm_concat
функция, потому что она недокументирована и обнаружена как обходной путь в Oracle 8i раз.
Со времен старого метода с пользовательской агрегатной функцией, обнаруженного Томом Кайтом, здесь есть несколько новых обходных путей, показанных в примерах ниже.
Все они воспроизведены в этой 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_path
а также xmlagg
был представлен, но оба хорошо работают на 10.2.0.4.0
Если вы на 11g попробуйте LISTAGG
вместо wm_concat
для начинающих.
Я только что видел этот пост относительно 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.
Вы, кажется, не делаете ничего плохого. С фиктивной табличной функцией для возврата данных, которые вы показали, 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
- может быть, ваш экземпляр тоже нет, но тогда он должен выдать ошибку?)