分隔CLOB字段报错
分隔CLOB字段报错,
今天写了一个函数 用来分隔clob字段中的数据.
新建了以下类型:
1,对象类型 o_gmpcreate or replace type o_gmp as object
(
groupid number,
cpids clob,
cchids clob
)2,对象数组类型 to_gmp:create or replace type to_gmp is tableof o_gmp
3,新建函数 f_split_clob:create or replace functionf_split_clob(vr_cur to_gmp,
vi_split in varchar2 default ',')
return to_gmp is
vi_pos11 int := 1;
vi_pos12 int := 1;
vi_pos21 int := 1;
vi_pos22 int := 1;
vt_parm to_gmp := to_gmp(o_gmp('', empty_clob(),empty_clob()));
vr_curpm o_gmp;
i int := 0;
vv_p varchar(40);
begin
for x in 1 .. vr_cur.count loop
vr_curpm := o_gmp(vr_cur(x).groupid,
vr_cur(x).cpids ,
vr_cur(x).cchids );
vi_pos11 := 1;
vi_pos12 := 1;
vi_pos21 := 1;
vi_pos22 := 1;
loop
vi_pos12 := instr(vr_curpm.cpids , vi_split, vi_pos11);
vi_pos22 := instr(vr_curpm.cchids , vi_split, vi_pos21);
exit when vi_pos12 = 0 or vi_pos22 = 0;
i := i + 1;
if not vt_parm.exists(i) then
vt_parm.extend;
vt_parm(i) := o_gmp('', empty_clob(),empty_clob());
end if;
vt_parm(i).groupid := vr_curpm.groupid;
if vi_pos12 > 0 then
vt_parm(i).cpids :=substr(vr_curpm.cpids ,
vi_pos11,
vi_pos12 - vi_pos11);
end if;
if vi_pos22 > 0 then
vt_parm(i).cchids := substr(vr_curpm.cchids ,
vi_pos21,
vi_pos22 - vi_pos21);
end if;
vi_pos11 := vi_pos12 + 1;
vi_pos21 := vi_pos22 + 1;
end loop;
vv_p := trim(substr(vr_curpm.cpids , vi_pos11, length(vr_curpm.cpids )));
if trim(vv_p) <> '' and trim(vv_p) is not null then
vt_parm.extend;
vt_parm(i) := o_gmp('', empty_clob(), empty_clob());
vt_parm(i).groupid := vr_curpm.groupid;
vt_parm(i).cpids := substr(vr_curpm.cpids ,
vi_pos11,
length(vr_curpm.cpids ));
vt_parm(i).cchids := nvl(substr(vr_curpm.cchids ,
vi_pos21,
vi_pos22 - vi_pos21),
'0');
end if;
end loop;
return vt_parm;
end;4,测试函数:
原始表中的数据表名: tmp_mpgroupclob
表结构: SQL> desc tmp_mpgroupclob
Name Type Nullable Default Comments
----------- ------------ -------- ------- --------
GROUPID VARCHAR2(10)
CPIDS CLOB Y
CCHIDS CLOB Y 表数据示例:SQL> select * from tmp_mpgroupclobwhere rownum<=3;
GROUPID CPIDS CCHIDS
--------------------------------------------------------------------------------------------------------------------------------------------------------------------------
1352 122231000100001152|122231000100001153|122231000100001152|1222310001000011521| 1|2|3|4|
目标表是 :tmp_mpgrouplist
结构是:SQL> desc tmp_mpgrouplist
Name Type Nullable Default Comments
----------- ------------ -------- ------- --------
GROUPID VARCHAR2(10) Y
CPIDS VARCHAR2(40) Y
CCHIDS VARCHAR2(10) Y
用以下代码把 tmp_mpgroupclob表中的数据分隔出来 插入到tmp_mpgrouplist中,安装 ‘|’ 号分隔开来。示例:
1352122231000100001152|122231000100001153|122231000100001152|1222310001000011521| 1|2|3|4|
变成
1352 122231000100001152 1
1352 122231000100001153 2
1352 122231000100001152 3
1352 122231000100001152 4
测试代码:declare
vto_gmp to_gmp;
vi_count int;
cursor cur1 is
select o_gmp(groupid, cpids , cchids )
from tmp_mpgroupclob
where rownum <= 420;
begin
open cur1;
loop
fetch cur1 bulk collect
into vto_gmp limit 10;
exit when cur1%notfound;
insert into tmp_mpgrouplist
(groupid, cpids , cchids )
select groupid, cpids , cchids
from table(f_split_clob(vto_gmp, '|'));
commit;
end loop;
close cur1;
end;
注意红色部分的条件。因为表 tmp_mpgroupclob中有记录几千条,当处理记录少的时候上述代码没有问题,但是当处理记录多了话比例上面处理420条,就会报错:
已经分批处理了。 fetch cur1 bulk collect
into vto_gmp limit 10;怎么还报错呢? ORA-04030: 在尝试分配 16396 字节 (koh-kghu call ,kollalos2) 时进程内存不足,
如果只处理 tmp_mpgroupclob 表中的少一些数据就不会报上面这个错误,这个错误时什么意思。是执行f_split_clob的错误,还是table函数的错误呢?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(9)
我上面写那个主要开销就是在处理临时表的时候,所以你可以将临时表换成内存表就可以了,我又修改了下:
,看起来不那么复杂吧:
复制代码
今天发现正则表达式虽然好用,但是效率太低了。
regexp_substr
就上面的这个例子我用 regexp_substr处理一个保护有2700个|符合分隔的clob字段需要几分钟,而用substr截取就是我的老方法只要几秒钟。相差太大了。
发现一个问题,如果用limit获取一个游标的数据。
当记录结果没有达到limit要求的数据时数据取不到。
fetch vrf_cur bulk collect
into vto_gmp limit 10;
比如这个,目的是取循环取10条,分批处理。但是当最后一轮还剩下没有10的话,这些记录就取不到了。相当于丢了。
这个我还没有用过。我试试
主要是你的这个串有规律,所以用了lead和ntile来取
regexp_substr(v_clob, '[^|]{1,}', 1, v_cnt);这个用得好啊。方法很简便
我也写了一个,练练手
复制代码
哎呀,自己找到问题了。
这个测试有1个目的:
测试使用table函数