Сыс соединить путем С данные типа CLOB
У меня есть ORA-01489: результат конкатенации строк слишком длинный ошибка выполнения этого запроса на базе данных Oracle 11g Enterprise Edition Release 11.2.0.4.0-64bit Production, PL / SQL Release 11.2.0.4.0-Production, CORE 11.2.0.4.0 Production, TNS для Linux: версия 11.2.0.4.0-Production, NLSRTL Version 11.2.0.4.0-Production:
SELECT "USER_PRIMARY_UNIT","LOGIN","FIRST_NAME","LAST_NAME","UNIT_ROLE"
FROM (
SELECT user_primary_unit,login, first_name, last_name,
LTRIM(MAX(SYS_CONNECT_BY_PATH(rights,' / '))
KEEP (DENSE_RANK LAST ORDER BY curr),' / ') AS UNIT_ROLE
FROM
(SELECT login,
first_name,
last_name,
user_primary_unit,
rights,
ROW_NUMBER() OVER (PARTITION BY login ORDER BY rights) AS curr,
ROW_NUMBER() OVER (PARTITION BY login ORDER BY rights) -1 AS prev
FROM (select member0_.login, member0_.first_name first_name, unit2.unit_name user_primary_unit, member0_.last_name last_name,
CONCAT(CONCAT(unit.unit_name, ' - '), role3_.role_name) rights
from
IOT_DEVICES.t_member member0_
inner join IOT_DEVICES.t_user member0_1_ on member0_.member_id=member0_1_.user_id
inner join IOT_DEVICES.t_playable_role playedrole1_ on member0_.member_id=playedrole1_.user_id
inner join IOT_DEVICES.t_unit_role unitrole2_ on playedrole1_.unit_role_id=unitrole2_.unit_role_id
inner join IOT_DEVICES.t_role role3_ on unitrole2_.role_id=role3_.role_id
inner join IOT_DEVICES.t_unit unit on unitrole2_.unit_id=unit.unit_id
inner join IOT_DEVICES.t_unit unit2 on unit2.unit_id=member0_1_.primary_unit_id
where current_date between playedrole1_.start_date and playedrole1_.end_date
order by unit.unit_name
))
GROUP BY login, first_name, last_name, user_primary_unit
CONNECT BY prev = PRIOR curr AND login = PRIOR login
START WITH curr = 1
)
ORDER BY user_PRIMARY_UNIT, FIRST_NAME, LAST_NAME;
Проблема с этим запросом заключается в использовании оператора CONCAT (||). Оператор Concat возвращает char1, объединенный с char2. То возвращаемая строка находится в том же наборе символов, что и char1. Поэтому здесь оператор concat пытается вернуть varchar2, который имеет предел 4000 символов и получает превышение. Эта проблема может также возникнуть, когда мы пытаемся объединить VARCHAR2 с CLOB. Поэтому здесь я хочу просто преобразовать свою первую строку в CLOB и избежать этой ошибки. После преобразования первой строки в CLOB оператор CONCAT возвращает строку типа CLOB
Поэтому я добавляю TO_CLOB для преобразования типов, но затем у меня появляется следующая ошибка:
ORA-00932: несогласованные типы данных: ожидаемый-получен CLOB
SELECT "USER_PRIMARY_UNIT","LOGIN","FIRST_NAME","LAST_NAME","UNIT_ROLE"
FROM (
SELECT user_primary_unit,login, first_name, last_name,
LTRIM(MAX(SYS_CONNECT_BY_PATH(rights,' / '))
KEEP (DENSE_RANK LAST ORDER BY curr),' / ') AS UNIT_ROLE
FROM
(SELECT login,
first_name,
last_name,
user_primary_unit,
rights,
ROW_NUMBER() OVER (PARTITION BY login ORDER BY rights) AS curr,
ROW_NUMBER() OVER (PARTITION BY login ORDER BY rights) -1 AS prev
FROM (select member0_.login, member0_.first_name first_name, unit2.unit_name user_primary_unit, member0_.last_name last_name,
TO_CLOB(CONCAT(CONCAT(unit.unit_name, ' - '), role3_.role_name)) rights
from
IOT_DEVICES.t_member member0_
inner join IOT_DEVICES.t_user member0_1_ on member0_.member_id=member0_1_.user_id
inner join IOT_DEVICES.t_playable_role playedrole1_ on member0_.member_id=playedrole1_.user_id
inner join IOT_DEVICES.t_unit_role unitrole2_ on playedrole1_.unit_role_id=unitrole2_.unit_role_id
inner join IOT_DEVICES.t_role role3_ on unitrole2_.role_id=role3_.role_id
inner join IOT_DEVICES.t_unit unit on unitrole2_.unit_id=unit.unit_id
inner join IOT_DEVICES.t_unit unit2 on unit2.unit_id=member0_1_.primary_unit_id
where current_date between playedrole1_.start_date and playedrole1_.end_date
order by unit.unit_name
))
GROUP BY login, first_name, last_name, user_primary_unit
CONNECT BY prev = PRIOR curr AND login = PRIOR login
START WITH curr = 1
)
ORDER BY user_PRIMARY_UNIT, FIRST_NAME, LAST_NAME;
Я также попытался использовать иерархию пакетов, определенную здесь, но затем я получил ORA - 00932: несогласованные типы данных: expected-got CLOB https://community.oracle.com/thread/965324?start=0&tstart=0
SELECT "USER_PRIMARY_UNIT","LOGIN","FIRST_NAME","LAST_NAME","UNIT_ROLE"
FROM (
SELECT user_primary_unit,login, first_name, last_name,
LTRIM(MAX(hierarchy.branch(level,rights,' / '))
KEEP (DENSE_RANK LAST ORDER BY curr),' / ') AS UNIT_ROLE
FROM
(SELECT login,
first_name,
last_name,
user_primary_unit,
rights,
ROW_NUMBER() OVER (PARTITION BY login ORDER BY rights) AS curr,
ROW_NUMBER() OVER (PARTITION BY login ORDER BY rights) -1 AS prev
FROM (select member0_.login, member0_.first_name first_name, unit2.unit_name user_primary_unit, member0_.last_name last_name,
TO_CLOB(CONCAT(CONCAT(unit.unit_name, ' - '), role3_.role_name)) rights
from
IOT_DEVICES.t_member member0_
inner join IOT_DEVICES.t_user member0_1_ on member0_.member_id=member0_1_.user_id
inner join IOT_DEVICES.t_playable_role playedrole1_ on member0_.member_id=playedrole1_.user_id
inner join IOT_DEVICES.t_unit_role unitrole2_ on playedrole1_.unit_role_id=unitrole2_.unit_role_id
inner join IOT_DEVICES.t_role role3_ on unitrole2_.role_id=role3_.role_id
inner join IOT_DEVICES.t_unit unit on unitrole2_.unit_id=unit.unit_id
inner join IOT_DEVICES.t_unit unit2 on unit2.unit_id=member0_1_.primary_unit_id
where current_date between playedrole1_.start_date and playedrole1_.end_date
order by unit.unit_name
))
GROUP BY login, first_name, last_name, user_primary_unit
CONNECT BY prev = PRIOR curr AND login = PRIOR login
START WITH curr = 1
)
ORDER BY user_PRIMARY_UNIT, FIRST_NAME, LAST_NAME;
Тогда я попробовал также с sys.stragg , но я получил Ора-00978: вложенные группы без группы
SELECT "USER_PRIMARY_UNIT","LOGIN","FIRST_NAME","LAST_NAME","UNIT_ROLE"
FROM (
SELECT user_primary_unit,login, first_name, last_name,
LTRIM(MAX(SYS_CONNECT_BY_PATH(rights,' / '))
KEEP (DENSE_RANK LAST ORDER BY curr),' / ') AS UNIT_ROLE
FROM
(SELECT login,
first_name,
last_name,
user_primary_unit,
rights,
ROW_NUMBER() OVER (PARTITION BY login ORDER BY rights) AS curr,
ROW_NUMBER() OVER (PARTITION BY login ORDER BY rights) -1 AS prev
FROM (select member0_.login, member0_.first_name first_name, unit2.unit_name user_primary_unit, member0_.last_name last_name,
sys.stragg(sys.stragg(unit.unit_name || ' - ' || role3_.role_name)) rights
from
IOT_DEVICES.t_member member0_
inner join IOT_DEVICES.t_user member0_1_ on member0_.member_id=member0_1_.user_id
inner join IOT_DEVICES.t_playable_role playedrole1_ on member0_.member_id=playedrole1_.user_id
inner join IOT_DEVICES.t_unit_role unitrole2_ on playedrole1_.unit_role_id=unitrole2_.unit_role_id
inner join IOT_DEVICES.t_role role3_ on unitrole2_.role_id=role3_.role_id
inner join IOT_DEVICES.t_unit unit on unitrole2_.unit_id=unit.unit_id
inner join IOT_DEVICES.t_unit unit2 on unit2.unit_id=member0_1_.primary_unit_id
where current_date between playedrole1_.start_date and playedrole1_.end_date
order by unit.unit_name
))
GROUP BY login, first_name, last_name, user_primary_unit
CONNECT BY prev = PRIOR curr AND login = PRIOR login
START WITH curr = 1
)
ORDER BY user_PRIMARY_UNIT, FIRST_NAME, LAST_NAME;
1 ответ:
Вы можете построить иерархию
CLOB
путь ссинтаксисом факторинга подзапросов это может работать очень медленно. Рассмотрим два столбца пути-один для результатаvarchar2
и один для результатаCLOB
. Построитьvarchar2
до тех пор, пока размер не позволит, и сохранитьNULL
вCLOB
пути, и переключиться наCLOB
, когда изvarchar2
емкости. Но это уже другой вопрос.with base as ( select level as id, case when level > 1 then level - 1 end as parent_id, dbms_random.string('X', 2000) as val from dual connect by level <= 50 ), hier(id, parent_id, val, path) as ( select b.id, b.parent_id, b.val, to_clob(concat('/', b.val)) as path from base b where b.parent_id is null union all select b.id, b.parent_id, b.val, concat(h.path, to_clob(' / '||b.val) ) from base b join hier h on h.id = b.parent_id ) select rownum, length(h.path) from hier h; ROWNUM LENGTH(H.PATH) 1 2001 2 4004 3 6007 4 8010 5 10013 6 12016 7 14019 8 16022 9 18025 10 20028 11 22031 12 24034 13 26037 14 28040 15 30043 16 32046 17 34049 18 36052 19 38055 20 40058 21 42061 22 44064 23 46067 24 48070 25 50073 26 52076 27 54079 28 56082 29 58085 30 60088 31 62091 32 64094 33 66097 34 68100 35 70103 36 72106 37 74109 38 76112 39 78115 40 80118 41 82121 42 84124 43 86127 44 88130 45 90133 46 92136 47 94139 48 96142 49 98145 50 100148