我正在将一个 TSQL 存储过程迁移到 PL/SQL,但遇到了一个问题 - Oracle 10g 中缺少 CONTINUE 关键字。
我读到 Oracle 11g 有这个新功能,但不幸的是升级不是一个选项。
在 10g 中是否有 CONTINUE 的替代方法?我认为重构存储过程的逻辑作为一种解决方法并不实际,因为我有一个外部循环,一个 IF,然后一个嵌套的 IF,在该 IF 的语句块末尾有 CONTINUE。
非常感谢任何帮助。谢谢。
你可以使用 goto 和标签 来模拟一个 continue。
DECLARE
done BOOLEAN;
BEGIN
FOR i IN 1..50 LOOP
IF done THEN
GOTO end_loop;
END IF;
<<end_loop>> -- not allowed unless an executable statement follows
NULL; -- add NULL statement to avoid error
END LOOP; -- raises an error without the previous NULL
END;
虽然有点复杂且只是一个假的例子,但你可以这样使用异常:
DECLARE
i NUMBER :=0;
my_ex exception;
BEGIN
FOR i IN 1..10
LOOP
BEGIN
IF i = 5 THEN
raise my_ex;
END IF;
DBMS_OUTPUT.PUT_LINE (i);
EXCEPTION WHEN my_ex THEN
NULL;
END;
END LOOP;
END;
declare
i integer;
begin
i := 0;
<<My_Small_Loop>>loop
i := i + 1;
if i <= 3 then goto My_Small_Loop; end if; -- => means continue
exit;
end loop;
end;
在 Oracle 11g 中,为了进行更多的搜索,它加入了一个 continue
语句,可以像这样使用:
SQL> BEGIN
2 FOR i IN 1 .. 5 LOOP
3 IF i IN (2,4) THEN
4 CONTINUE;
5 END IF;
6 DBMS_OUTPUT.PUT_LINE('Reached on line ' || TO_CHAR(i));
7 END LOOP;
8 END;
9 /
Reached on line 1
Reached on line 3
Reached on line 5
PL/SQL procedure successfully completed.
你能否将这些IF语句重构为一个函数,并在适当的位置返回(必要时尽早返回)。然后控制流会在循环的正确位置继续。
这样说你明白了吗?
虽然不太优雅,但很简单:
DECLARE
done BOOLEAN;
BEGIN
FOR i IN 1..50 LOOP
IF done THEN
NULL;
ELSE
<do loop stuff>;
END IF;
END LOOP;
END;
DECLARE
done BOOLEAN;
BEGIN
FOR i IN 1..50 LOOP
EXIT WHEN done;
END LOOP;
END;
如果你想要从一些嵌套的循环和逻辑中退出,这可能不够用,但比几个GOTO和NULL更清晰。
for i in .. tab_xy.count loop
CONTINUE WHEN some_condition(tab_xy(i));
do_process(tab_xy(i));
end loop;
像这样:
循环遍历表tab_xy的记录。
如果记录满足某些条件,则继续,否则忽略此记录。
处理该记录。
这种解释完全错误,但是如果你将PL/SQL代码想象成一种烹饪配方并大声朗读,这种情况可能会发生。
事实上,昨天发生在一个非常有经验的开发同事身上。