【www.arisingsemi.com--IT认证】

continue用法
因为以前看到有的同事sql脚本中的一些写法,本意是使用oracle的continue用法,结果却事与愿违。我正好周末无事时写了一个脚本,用到这个,现分享给大家。
我们知道,像C、JAVA、C#等编程语言中都有continue,连python这种解释性语言都有continue,那oracle有没有continue呢。
具体说,是有的,但要在oracle 11g之后才有。那对于10g跟之前的版本要如何实现continue的用法呢。
看下面的脚本,只选了部分的内容:
for c in get_info(v_seg) loop
if (_analyzed is null or
round(sysdate - _analyzed) > v_days) then
begin
dbms__table_stats(ownname          => ,
tabname          => _name,
partname        => null,
estimate_percent => 0.0001);
exception
when others then
null;
end;
end if;
end loop;
这段sql主要用途是对一个cursor中的所有表进行统计信息收集,其实完全可以使用一个这样的循环就可以搞定的:
for c in get_info(v_seg) loop
if (_analyzed is null or
round(sysdate - _analyzed) > v_days) then
dbms__table_stats(ownname          => ,
tabname          => _name,
partname        => null,
estimate_percent => 0.0001);
end if;
end loop;
但是,由于统计信息收集时,有时会遇到权限不足(按我们的库经常会遇到)的问题,如果报错,将跳出此循环,其他的表将得不到统计信息收集。
这时需要我们使用continue,来跳过此循环,去分析下一个表。但此库正好是一个10g的库,不能使用11g的continue关键字,更何况我们写脚本,一定要做到的一点是,通用,即在常用的oracle版本(目前一般是指8i-11g,当然我们就是10g-11g)中都能使用。于是我们使用了嵌套循环的办法,即加入一个新的pl/sql语句块,并加入异常处理,即让异常的捕获是在循环之内,还不是循环之外的异常去捕获到它。
不过这里就比较简单的一个null了,当然可以使用一些执行纪录等。当业务较为复杂时,可以建立自定义的异常来捕获:
declare
pi constant number(9, 7) := 3.1415927;
radius integer(5);
area  number(14, 2);
e_userdefinedexception exception;
pragma exception_init(e_userdefinedexception, -1401);
begin
radius := 0;
loop
radius := radius + 1;
begin
if radius = 4 then
raise e_userdefinedexception;
else
area := pi * power(radius, 2);
insert into areas values (radius, area);
exit when area > 100;
end if;
exception
when e_userdefinedexception then
null;
end;
end loop;
commit;
end;
还有一种办法是在pl/sql的声明部分使用procedure,不过原理上面是一样的。我们再说下可以使用goto的方法:
declare
pi  constant number (9, 7)  := 3.1415927;
radius        integer (5);
area          number (14, 2);
begin
radius := 0;
loop

radius := radius + 1;
if radius = 4
then
goto here;
else
area := pi * power (radius, 2);
insert into areas
values (radius, area);
exit when area > 100;
end if;
end loop;
commit;
end;
貌似goto看起来更简洁,不过我们知道C语言的灵魂是指针,但这也是goto的原理,也是被诟病的地方,即goto破坏程序的可读性跟可维护性。Pl/sql也是是高级编程语言,同样也不推荐使用goto的方法,因为非常容易出错,导致业务逻辑出现问题。应优先使用第一种方法。另外,我们说到11g有了正统的continue,我们看下它的用法,其实跟普通编程语言中的用法完全一样:
declare
total int := 0;
begin
for i in 1 .. 10 loop
if mod(i, 2) = 0 then
continue;
end if;
total := total + i;
end loop;
dbms__line(total);
end;。

本文来源:http://www.arisingsemi.com/it/55892/