因为以前看到有的同事sql脚本中的一些写法,本意是使用oracle的continue用法,结果却事与愿违。我正好周末无事时写了一个脚本,用到这个,现分享给大家。
我们知道,像C、JAVA、C#等编程语言中都有continue,连python这种解释性语言都有continue,那oracle有没有continue呢?具体说,是有的,但要在oracle 11g之后才有。那对于10g跟之前的版本要如何实现continue的用法呢?看下面的脚本,只选了部分的内容:
for c in get_info(v_seg) loop
if (c.last_analyzed is null or
round(sysdate - c.last_analyzed) > v_days) then
begin
dbms_stats.gather_table_stats(ownname => c.owner,
tabname => c.table_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 (c.last_analyzed is null or
round(sysdate - c.last_analyzed) > v_days) then
dbms_stats.gather_table_stats(ownname => c.owner,
tabname => c.table_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
nullisnull的用法;
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
<<here>>
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_output.put_line(total);
end;
版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系QQ:729038198,我们将在24小时内删除。
发表评论