我有一个 ORA-01489:字符串连接的结果太长错误在Oracle Database 11g企业版11.2.0.4.0上执行此查询时出错 - 64位生产,PL / SQL版本11.2 .0.4.0 - 生产,核心11.2.0.4.0生产,Linux的TNS:版本11.2.0.4.0 - 生产,NLSRTL版本11.2.0.4.0 - 生产:
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运算符返回与char2连接的char1。返回的字符串与char1的字符集相同。所以这里concat运算符试图返回varchar2,它有4000个字符的限制并且超出了。当我们尝试使用CLOB CONCAT VARCHAR2时,也可能出现此问题。所以在这里我只想将其第一个字符串转换为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;
我也尝试使用这里定义的Hierarchy包,但后来我得到了一个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 ,但我得到了一个 ORA-00978:没有GROUP BY的嵌套组函数
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;
答案 0 :(得分:1)
您可以使用subquery factoring syntax构建层次结构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
答案 1 :(得分:0)
您可能会找到此页面,因为您正试图汇总长度超过4000个字符的字符串,并记住the different techniques。
如果是这样,我根据@B Samedi的回答创建了一个小例子,当您无法使用user defined aggregates
时可以为您提供帮助with dummy_text as (
select 'teststring ' || rownum str from dual connect by rownum < 2
)
, indexed_strings as (
select str, row_number() over (order by 'x') rn, ',' separator from dummy_text
)
, hier (str, lvl) as (
select to_clob(i.str), rn from indexed_strings i where rn = (select max(rn) from indexed_strings)
union all
select concat(to_clob(concat(i.str, i.separator)), h.str), h.lvl - 1 from indexed_strings i join hier h on h.lvl - 1 = i.rn
)
select str from hier where lvl = 1