一个游标循环遍历中,异常如何处理?

oraclemch 2009-09-16 09:55:34
create or replace procedure c1
is
cursor c1 is select cid,.... from tb where .....;
begin
open c1
loop c1 into v_id,......
update tb1 set column1=v_c1,...... where id=v_id ......
commit;
end loop;
exception
when others then
--异常如何处理,v_id为主键id
insert into tb_expo(eid,......)values(v_id,.....)
rollback;
end

--这里如果update失败了,如何处理,我的目的是在异常处理的时候记录下v_id,
--然后回滚这个update操作,然后继续遍历剩下的游标记录,这个思路如何实现?
...全文
393 19 打赏 收藏 转发到动态 举报
写回复
用AI写文章
19 条回复
切换为时间正序
请发表友善的回复…
发表回复
呼啦11111 2011-07-12
  • 打赏
  • 举报
回复
悲剧啊,这么简单的问题,被各位大侠弄的这么复杂
游标里面处理
新开一个BEGIN EXCEPTION end就可以了
小灰狼W 2009-09-16
  • 打赏
  • 举报
回复
[Quote=引用 6 楼 oraclemch 的回复:]
引用 3 楼 wildwave 的回复:
SQL codecreateorreplaceprocedure c1iscursor c1isselect cid,....from tbwhere .....;beginopen c1
      loop c1into v_id,...... < <inner1>>commit;update tb1set column1=v_c1,......where id=v_id ......
                     
      exceptionwhen othersthenrollback;--异常如何处理,v_id为主键idinsertinto tb_expo(eid,......)values(v_id,.....);end inner1;end loop;end
将异常放在内部块里处理

你的commit为什么在update前面?
[/Quote]
commit放前面也不是很好的解决办法
改下
create or replace procedure c1
is
cursor c1 is select cid,.... from tb where .....;
begin
open c1
loop c1 into v_id,......
<<inner1>>
savepoint a;
update tb1 set column1=v_c1,...... where id=v_id ......

exception
when others then
rollback to a; --异常如何处理,v_id为主键id
insert into tb_expo(eid,......)values(v_id,.....);
end inner1;
end loop;
commit;
end

你把rollback放insert 后面,等于插入白做了
到最后再提交
oraclemch 2009-09-16
  • 打赏
  • 举报
回复
[Quote=引用 3 楼 wildwave 的回复:]
SQL codecreateorreplaceprocedure c1iscursor c1isselect cid,....from tbwhere .....;beginopen c1
loop c1into v_id,......<<inner1>>commit;update tb1set column1=v_c1,......where id=v_id ......

exceptionwhen othersthenrollback;--异常如何处理,v_id为主键idinsertinto tb_expo(eid,......)values(v_id,.....);end inner1;end loop;end
将异常放在内部块里处理
[/Quote]
你的commit为什么在update前面?
oraclemch 2009-09-16
  • 打赏
  • 举报
回复
[Quote=引用 4 楼 wildwave 的回复:]
open c1
      loop c1 into v_id,......这些格式有问题
不过在这里不是你的重点
格式自己改好
[/Quote]

谢谢狂狼,我去试试!
小灰狼W 2009-09-16
  • 打赏
  • 举报
回复
open c1
loop c1 into v_id,......这些格式有问题
不过在这里不是你的重点
格式自己改好
小灰狼W 2009-09-16
  • 打赏
  • 举报
回复
create or replace procedure c1
is
cursor c1 is select cid,.... from tb where .....;
begin
open c1
loop c1 into v_id,......
<<inner1>>
commit;
update tb1 set column1=v_c1,...... where id=v_id ......

exception
when others then
rollback; --异常如何处理,v_id为主键id
insert into tb_expo(eid,......)values(v_id,.....);
end inner1;
end loop;
end

将异常放在内部块里处理
oraclemch 2009-09-16
  • 打赏
  • 举报
回复
[Quote=引用 1 楼 ojuju10 的回复:]
异常后,回滚,退出了存储过程
[/Quote]

那就表示,游标c1只执行了异常前的一部分,剩下的就没有执行了?
我想要的效果是,异常的记录到异常表里面去,然后继续遍历游标,继续update操作啊,这个怎么实现?
ojuju10 2009-09-16
  • 打赏
  • 举报
回复
异常后,回滚,退出了存储过程
superjava_2006 2009-09-16
  • 打赏
  • 举报
回复
异常处理里面需要加入begin……end,也就是then后加入begin,异常处理的语句最后加入end;
oraclemch 2009-09-16
  • 打赏
  • 举报
回复
[Quote=引用 16 楼 wildwave 的回复:]
引用 15 楼 oraclemch 的回复:
引用 14 楼 wildwave 的回复:
引用 13 楼 oraclemch 的回复:
引用 11 楼 wildwave 的回复:
编译错误还是运行错误
我把你的语句拷过来编译成功


在plsql里面edit存储过程,点击 F8键 编译失败。

加上begin再试试
下面有end inner1
上面没有begin
所以出错


那个 < <inner1>>起啥作用呢?

一个标签,声明一个内部语句块
[/Quote]

哦,知道了!
小灰狼W 2009-09-16
  • 打赏
  • 举报
回复
[Quote=引用 15 楼 oraclemch 的回复:]
引用 14 楼 wildwave 的回复:
引用 13 楼 oraclemch 的回复:
引用 11 楼 wildwave 的回复:
编译错误还是运行错误
我把你的语句拷过来编译成功


在plsql里面edit存储过程,点击 F8键 编译失败。

加上begin再试试
下面有end inner1
上面没有begin
所以出错


那个 < <inner1>>起啥作用呢?
[/Quote]
一个标签,声明一个内部语句块
oraclemch 2009-09-16
  • 打赏
  • 举报
回复
[Quote=引用 14 楼 wildwave 的回复:]
引用 13 楼 oraclemch 的回复:
引用 11 楼 wildwave 的回复:
编译错误还是运行错误
我把你的语句拷过来编译成功


在plsql里面edit存储过程,点击 F8键 编译失败。

加上begin再试试
下面有end inner1
上面没有begin
所以出错
[/Quote]

那个<<inner1>>起啥作用呢?
小灰狼W 2009-09-16
  • 打赏
  • 举报
回复
[Quote=引用 13 楼 oraclemch 的回复:]
引用 11 楼 wildwave 的回复:
编译错误还是运行错误
我把你的语句拷过来编译成功


在plsql里面edit存储过程,点击 F8键 编译失败。
[/Quote]
加上begin再试试
下面有end inner1
上面没有begin
所以出错
oraclemch 2009-09-16
  • 打赏
  • 举报
回复
[Quote=引用 11 楼 wildwave 的回复:]
编译错误还是运行错误
我把你的语句拷过来编译成功
[/Quote]

在plsql里面edit存储过程,点击 F8键 编译失败。
小灰狼W 2009-09-16
  • 打赏
  • 举报
回复
忘了在inner1标签下面加begin了。。。
小灰狼W 2009-09-16
  • 打赏
  • 举报
回复
编译错误还是运行错误
我把你的语句拷过来编译成功
oraclemch 2009-09-16
  • 打赏
  • 举报
回复
create or replace procedure YH_TMQY_MERGER_Update(
out_flag out number,
out_message out varchar2
)
/*
号百优化,增量同名企业归并、设置不供查可查询显示存储过程
skyman 2009-09-14
*/
is
v_customer_id t_customer_tel.customer_id%type;
v_out_code number;
v_out_message varchar2(200);
v_num number:=0;
v_search_telid varchar2(40);
--执行过程标记
v_flag number;

--定义增量游标
cursor cids is
select t.customer_id
from t_customer_tel t,
YH_TRS_QYCY$_TEMP y,
t_customer c
where t.telephone is not null
and t.check_status='1'
and y.custemer_tel_id=t.customer_tel_id
and t.customer_id=c.customer_id and c.type IN (1,2); --企业类型

--存放所有v_customer_id下面需要归并的customer_tel_id记录。
type tel_record is record
(
telid t_customer_tel.customer_tel_id%type,
flag t_customer_tel.merger_flag%type
);
type tel_records is table of tel_record index by binary_integer;
telids tel_records;

begin

v_flag:=0;

--从增量表里面取得telid以及对应的customer_id。
insert into YH_TRS_QYCY$_TEMP(SEQ_ID, CUSTEMER_TEL_ID, SQL_TYPE, TRS_FLAG)
select yh_seq_id.nextval, t.xh, t.sql_type, t.trs_flag
from TRS_QYCY$_TEMP t;

--从异常信息表里面取得前一天执行失败的tel_id记录。
insert into YH_TRS_QYCY$_TEMP(SEQ_ID, CUSTEMER_TEL_ID, SQL_TYPE, TRS_FLAG)
select yh_seq_id.nextval, y.exec_pk_auto_id,null,null
from YH_EXCEPTION y
where trunc(sysdate)-trunc(y.post_time)=1
and y.exec_column_name='customer_tel_id'
and y.exec_table_name='t_customer_tel'
and y.exec_object_name='YH_TMQY_MERGER_Update';




open cids;
loop
fetch cids into v_customer_id;
exit when cids%notfound;
<<inner1>>
--1,设置增量企业归并标记,存放在cids里面。
select
t.customer_tel_id,
case when count(t.customer_id)over(partition by t.customer_id)=1 then 1
else
(row_number() over (partition by t.customer_id order by t.ownership asc,t.source desc,t.is_extention asc,t.customer_tel_id desc ))+1
end as flag
bulk collect into telids
from t_customer_tel t
where t.customer_id=v_customer_id
and ( (t.is_open=0 and t.is_search=0) or t.isOpen_flag='1')
and t.telephone is not null
and t.check_status='1'
and not exists( select 1 from t_dc_discount d where d.customer_id=t.customer_id)--没有折扣信息
and t.prompt is not null
and not exists( select 1 from t_customer_info i where i.customer_tel_id=t.customer_tel_id)--没有深度信息
and not exists--没有区域信息
(
select 1
from t_product p,t_query_recommend q
where p.customer_tel_id=q.customer_tel_id
and q.product_type in ('1','2')
and p.product_status='2'
and q.busi_area is not null
and q.customer_tel_id=t.customer_tel_id
)
and not exists--没有关键词业务
(
select 1
from t_product p,t_query_recommend r
where p.product_status='2'
and p.product_spec_id in ('A101','A102')
and p.customer_tel_id=t.customer_tel_id
and r.product_id=p.product_id
);

--设置同名归并增量标记
for i in telids.first .. telids.last loop
update t_customer_tel t
set t.merger_flag=telids(i).flag
where t.customer_tel_id=telids(i).telid;

end loop;

--2,设置增量不可供查可查询显示标记。
select count(*) into v_num
from t_customer_tel t
where t.customer_id=v_customer_id
and t.is_search=0 and t.is_open=0;
v_search_telid:='';
if(v_num>0) then
update t_customer_tel t
set t.isopen_flag=0
where t.customer_id=v_customer_id;
else
--将旧的不不可供查可查询显示标记删除掉。
update t_customer_tel t
set t.isopen_flag=0
where t.customer_id=v_customer_id
and t.isopen_flag=1;

--重新设置不可供查可查询显示标记
select b.customer_tel_id into v_search_telid
from
(
select a.customer_id,a.customer_tel_id,
row_number() over (partition by a.customer_id order by a.qyzj_flag asc,a.customer_tel_id desc) as rowflag
from
(
select t2.customer_id,t2.customer_tel_id, t2.is_open,t2.is_search,
case when t2.is_extention=1 then 1 else 2 end as qyzj_flag
from t_customer_tel t2
where t2.customer_id=v_customer_id
and (t2.is_open!=0 or t2.is_search!=0)
and not exists(select 1 from t_customer_tel t1 where t1.customer_id=t2.customer_id and t1.is_open=0 AND t1.is_search=0)
and t2.telephone is not null
)a
)b where b.rowflag=1;
update t_customer_tel t
set t.isopen_flag=1
where t.customer_tel_id=v_search_telid;
end if;
commit;

--异常处理,编译的时候在这里exception一句里面报上面的错误。
exception

when others then
out_flag:=0;
v_out_message:=sqlerrm;
rollback; --异常如何处理,v_id为主键id
insert into yh_exception
(exec_pk_auto_id,exec_column_name,exec_table_name,exec_object_name,exception_info)
values(v_customer_id,'customer_id','t_customer_tel','YH_TMQY_MERGER_Update','v_flag:'||v_flag||', '||v_out_message);
commit;
end inner1;

end loop;
close cids;

out_flag:=1;

--异常处理

-- return ;
end YH_TMQY_MERGER_Update;
小灰狼W 2009-09-16
  • 打赏
  • 举报
回复
[Quote=引用 8 楼 oraclemch 的回复:]
引用 7 楼 wildwave 的回复:
引用 6 楼 oraclemch 的回复:
引用 3 楼 wildwave 的回复:
SQL codecreateorreplaceprocedure c1iscursor c1isselect cid,....from tbwhere .....;beginopen c1
      loop c1into v_id,...... < <inner1>>commit;update tb1set column1=v_c1,......where id=v_id ......
                     
      exceptionwhen othersthenrollback;--异常如何处理,v_id为主键idinsertinto tb_expo(eid,......)values(v_id,.....);end inner1;end loop;end
将异常放在内部块里处理

你的commit为什么在update前面?

commit放前面也不是很好的解决办法
改下
SQL codecreateorreplaceprocedure c1iscursor c1isselect cid,....from tbwhere .....;beginopen c1
      loop c1into v_id,...... < <inner1>>
        savepoint a;update tb1set column1=v_c1,......where id=v_id ......
                     
      exceptionwhen othersthenrollbackto a;--异常如何处理,v_id为主键idinsertinto tb_expo(eid,......)values(v_id,.....);end inner1;end loop;commit;end
你把rollback放insert 后面,等于插入白做了
到最后再提交


为什么我编译的时候会报如下错误呢?

Compilation errors for PROCEDURE ADD114.YH_TMQY_MERGER_UPDATE

Error: PLS-00103: Encountered the symbol "EXCEPTION" when expecting one of the following:
     
          begin case declare end exit for goto if loop mod null pragma
          raise return select update while with <an identifier>
          <a double-quoted delimited-identifier> <a bind variable> < <
          close current delete fetch lock insert open rollback
          savepoint set sql execute commit forall merge pipe
Line: 149
Text: exception

Error: PLS-00103: Encountered the symbol "LOOP" when expecting one of the following:
     
          ;
Line: 161
Text: end loop;

Error: PLS-00103: Encountered the symbol "end-of-file" when expecting one of the following:
     
          end not pragma final instantiable order overriding static
          member constructor map
Line: 169
Text: end YH_TMQY_MERGER_Update;
[/Quote]
你将你执行的语句贴出来,
标出报错的所在行
oraclemch 2009-09-16
  • 打赏
  • 举报
回复
[Quote=引用 7 楼 wildwave 的回复:]
引用 6 楼 oraclemch 的回复:
引用 3 楼 wildwave 的回复:
SQL codecreateorreplaceprocedure c1iscursor c1isselect cid,....from tbwhere .....;beginopen c1
      loop c1into v_id,...... < <inner1>>commit;update tb1set column1=v_c1,......where id=v_id ......
                     
      exceptionwhen othersthenrollback;--异常如何处理,v_id为主键idinsertinto tb_expo(eid,......)values(v_id,.....);end inner1;end loop;end
将异常放在内部块里处理

你的commit为什么在update前面?

commit放前面也不是很好的解决办法
改下
SQL codecreateorreplaceprocedure c1iscursor c1isselect cid,....from tbwhere .....;beginopen c1
loop c1into v_id,......<<inner1>>
savepoint a;update tb1set column1=v_c1,......where id=v_id ......

exceptionwhen othersthenrollbackto a;--异常如何处理,v_id为主键idinsertinto tb_expo(eid,......)values(v_id,.....);end inner1;end loop;commit;end
你把rollback放insert 后面,等于插入白做了
到最后再提交
[/Quote]

为什么我编译的时候会报如下错误呢?

Compilation errors for PROCEDURE ADD114.YH_TMQY_MERGER_UPDATE

Error: PLS-00103: Encountered the symbol "EXCEPTION" when expecting one of the following:

begin case declare end exit for goto if loop mod null pragma
raise return select update while with <an identifier>
<a double-quoted delimited-identifier> <a bind variable> <<
close current delete fetch lock insert open rollback
savepoint set sql execute commit forall merge pipe
Line: 149
Text: exception

Error: PLS-00103: Encountered the symbol "LOOP" when expecting one of the following:

;
Line: 161
Text: end loop;

Error: PLS-00103: Encountered the symbol "end-of-file" when expecting one of the following:

end not pragma final instantiable order overriding static
member constructor map
Line: 169
Text: end YH_TMQY_MERGER_Update;

17,082

社区成员

发帖
与我相关
我的任务
社区描述
Oracle开发相关技术讨论
社区管理员
  • 开发
  • Lucifer三思而后行
  • 卖水果的net
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

试试用AI创作助手写篇文章吧