oracle - 使用带有 CLOB 参数的连接语句
Posted
技术标签:
【中文标题】oracle - 使用带有 CLOB 参数的连接语句【英文标题】:oracle - Use connect by statement with CLOB parameter 【发布时间】:2014-03-05 12:05:13 【问题描述】:我的程序
CREATE OR REPLACE PROCEDURE my_procedure(res OUT SYS_REFCURSOR , p_LstKH CLOB)
AS
CURSOR c_dsKH
IS
SELECT TO_NUMBER(REGEXP_SUBSTR(p_LstKH,'[^,]+', 1, level)) value FROM dual
CONNECT BY REGEXP_SUBSTR(p_LstKH, '[^,]+', 1, level) IS NOT NULL;
BEGIN
...
END;
我想拆分长字符串p_LstKH,然后放入CURSOR c_dsKH。示例:p_LstKH = '1,2,....,10000'
c_dsKH.value
1
2
...
10000
但是,当我执行该过程时,我收到错误“没有足够的内存用于通过操作连接”。 我尝试将参数 p_LstKH CLOB 替换为 p_LstKH VARCHAR2,然后出现其他错误“ORA-06502: PL/SQL: numeric or value error: string buffer too small”。
我现在该怎么办?简单地说,我想拆分一个长字符串。 谢谢大家!
【问题讨论】:
正则表达式最多可以包含 512 个字节 check here。您可以创建一个全局临时表并编写一个过程来存储结果。并从 GT 表中查询。 @simplify_life - pattern 最多可达 512 个字节;这里的模式是'[^,]+'
,只有 5 个。这是为大输入字符串生成的级别数。
@Alex..Correct.. 我的错
【参考方案1】:
您可以根据逗号进行自己的拆分,并使用流水线函数返回值:
create or replace function split_clob(p_lstkh clob)
return sys.odcivarchar2list pipelined
as
start_pos pls_integer := 0;
end_pos pls_integer := 0;
clob_length pls_integer;
str varchar2(4000);
begin
clob_length := dbms_lob.getlength(p_lstkh);
while end_pos <= clob_length loop
start_pos := end_pos + 1;
end_pos := dbms_lob.instr(p_lstkh, ',', start_pos, 1);
if end_pos <= 0 then
end_pos := clob_length + 1;
end if;
str := dbms_lob.substr(p_lstkh, end_pos - start_pos, start_pos);
pipe row (str);
end loop;
end;
/
那么你可以把它当作一个表格:
select * from table(split_clob('X,Y,Z'));
COLUMN_VALUE
------------
X
Y
Z
如果您仍然想要作为参考游标,您的过程可以使用该选择作为游标,而不是连接方式。
作为一个演示,展示它与超过 32k 的实际(合成)clob 一起使用:
declare
clob_val clob := 'A,B,C,D,E,F,G,H,I';
begin
for i in 1..2000 loop
dbms_lob.append(clob_val, ',A,B,C,D,E,F,G,H,I');
end loop;
dbms_output.put_line('Clob size: ' || dbms_lob.getlength(clob_val));
for r in (select * from table(split_clob(clob_val)) where rownum < 6) loop
dbms_output.put_line(r.column_value);
end loop;
end;
/
anonymous block completed
Clob size: 36017
A
B
C
D
E
【讨论】:
非常感谢。你是我的英雄亚历克斯普尔 :)【参考方案2】:这应该可以工作,但它需要一个返回 refcursor 的函数。如果您可以使用它:
create or replace
function splitter(pc CLOB) return sys_refcursor
as
lc sys_refcursor;
begin
open lc for
with s(tot, sub, offset) as (
select pc||',' tot,
dbms_lob.substr(pc, dbms_lob.instr(pc, ',', 1)-1, 1) sub,
dbms_lob.instr(pc, ',', 1)+1 offset
from dual
union all
select tot,
dbms_lob.substr(tot, dbms_lob.instr(tot, ',', offset+1)-offset, offset),
dbms_lob.instr(tot, ',', offset+1)+1
from s
where offset < dbms_lob.getlength(tot)
)
select sub
from s;
return lc;
end;
/
var c refcursor;
exec :c := splitter('a,b,c,d,e,f');
print c;
【讨论】:
以上是关于oracle - 使用带有 CLOB 参数的连接语句的主要内容,如果未能解决你的问题,请参考以下文章
Oracle 存储过程因复杂类型的 clob 而失败,并带有 ORA-22922