Когда я пытаюсь использовать WMSYS.WM_CONCAT с Oracle XE 10g, я получаю ошибку компиляции: ORA-00904: "WMSYS"."WM_CONCAT": invalid identifier
. Может ли кто-нибудь убедиться, что это действительно связано с тем, что XE не имеет этой (недокументированной) функции? Если да, есть ли способ включить его в XE?Использование WMSYS.WM_CONCAT с Oracle XE 10g
3
A
ответ
3
Я нашел пару ссылочных сайтов, но не повезло. В конце концов я написал свою собственную функцию для обработки конкатенации.
CREATE or replace FUNCTION CONCAT_LIST(cur SYS_REFCURSOR, sep Varchar2) RETURN VARCHAR2 IS
ret VARCHAR2(32000);
tmp VARCHAR2(4000);
BEGIN
loop
fetch cur into tmp;
exit when cur%NOTFOUND;
if ret is null then
ret := tmp;
else
ret := ret || sep || tmp;
end if;
end loop;
RETURN ret; END;/
Тогда можно назвать
SELECT distinct CONCAT_LIST(CURSOR(SELECT id FROM test_table1), ',') test_table1 FROM dual
3
Источник: link.
Просто создать эту функцию самостоятельно:
CREATE OR REPLACE TYPE wm_concat_impl
AUTHID CURRENT_USER
AS OBJECT (
curr_str VARCHAR2 (32767),
STATIC FUNCTION odciaggregateinitialize (sctx IN OUT wm_concat_impl)
RETURN NUMBER,
MEMBER FUNCTION odciaggregateiterate (
SELF IN OUT wm_concat_impl,
p1 IN VARCHAR2
)
RETURN NUMBER,
MEMBER FUNCTION odciaggregateterminate (
SELF IN wm_concat_impl,
returnvalue OUT VARCHAR2,
flags IN NUMBER
)
RETURN NUMBER,
MEMBER FUNCTION odciaggregatemerge (
SELF IN OUT wm_concat_impl,
sctx2 IN wm_concat_impl
)
RETURN NUMBER
);
/
CREATE OR REPLACE TYPE BODY wm_concat_impl
IS
STATIC FUNCTION odciaggregateinitialize (sctx IN OUT wm_concat_impl)
RETURN NUMBER
IS
BEGIN
sctx := wm_concat_impl (NULL);
RETURN odciconst.success;
END;
MEMBER FUNCTION odciaggregateiterate (
SELF IN OUT wm_concat_impl,
p1 IN VARCHAR2
)
RETURN NUMBER
IS
BEGIN
IF (curr_str IS NOT NULL)
THEN
curr_str := curr_str || ',' || p1;
ELSE
curr_str := p1;
END IF;
RETURN odciconst.success;
END;
MEMBER FUNCTION odciaggregateterminate (
SELF IN wm_concat_impl,
returnvalue OUT VARCHAR2,
flags IN NUMBER
)
RETURN NUMBER
IS
BEGIN
returnvalue := curr_str;
RETURN odciconst.success;
END;
MEMBER FUNCTION odciaggregatemerge (
SELF IN OUT wm_concat_impl,
sctx2 IN wm_concat_impl
)
RETURN NUMBER
IS
BEGIN
IF (sctx2.curr_str IS NOT NULL)
THEN
SELF.curr_str := SELF.curr_str || ',' || sctx2.curr_str;
END IF;
RETURN odciconst.success;
END;
END;
/
CREATE OR REPLACE FUNCTION wm_concat (p1 VARCHAR2)
RETURN VARCHAR2
AGGREGATE USING wm_concat_impl;
/
2
Рекомендуется не использовать WM_CONCAT, так как это не документировано, и она была удалена из 12с версии. См Why not use WM_CONCAT function in Oracle?
Если вы на 11gR2 и выше, используйте LISTAGG.
Для версии до 11g где LISTAGG
не поддерживается, вы можете использовать ROW_NUMBER() и SYS_CONNECT_BY_PATH функции.
Например,
SELECT deptno,
LTRIM(MAX(SYS_CONNECT_BY_PATH(ename,','))
KEEP (DENSE_RANK LAST ORDER BY curr),',') AS employees
FROM (SELECT deptno,
ename,
ROW_NUMBER() OVER (PARTITION BY deptno ORDER BY ename) AS curr,
ROW_NUMBER() OVER (PARTITION BY deptno ORDER BY ename) -1 AS prev
FROM emp)
GROUP BY deptno
CONNECT BY prev = PRIOR curr AND deptno = PRIOR deptno
START WITH curr = 1;
DEPTNO EMPLOYEES
---------- --------------------------------------------------
10 CLARK,KING,MILLER
20 ADAMS,FORD,JONES,SCOTT,SMITH
30 ALLEN,BLAKE,JAMES,MARTIN,TURNER,WARD
3 rows selected.
Спасибо, я действительно интересно, может ли эта функция включена. Лучшей альтернативой, которую я нашел, была пользовательская функция агрегации: http://www.oracle-base.com/articles/misc/StringAggregationTechniques.php. Я переименовал функцию из string_agg в wm_concat, с тех пор я могу поделиться хранимыми процедурами с моими сотрудниками, у которых есть полный оракул 10g (метод, приведенный в статье, позволяет использовать тот же синтаксис, который вы будете использовать с реальным wm_concat, - пока вы не используя скрипты, которые полностью соответствуют wm_concat с wm_sys) –
Это довольно пятно. У меня есть несколько больших запросов, которые я использую для этой функции. Как только я вернусь в офис, я создам новый и проверю производительность. Мне это любопытно. Благодаря! – RandyB
Прохладный, я бы хотел услышать ваши результаты, когда вы закончите. –