我正在将 TSQL 存储过程迁移到 PL/SQL 并且遇到了一个问题 - Oracle 10g 中缺少 CONTINUE 关键字。
我读到Oracle 11g 有这个作为一个新特性,但不幸的是升级不是一个选项。
10g 中的 CONTINUE 有什么替代品吗?我认为将 SP 的逻辑重构为一种变通方法是不切实际的,因为我有一个外部循环、一个 IF,然后是一个嵌套的 IF,然后是该 IF 中语句块末尾的 CONTINUE。
任何帮助将不胜感激,干杯。
您可以使用goto 和 labels模拟继续。
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;
事实上,PL SQL 确实有一些东西可以代替 CONTINUE。您所要做的就是在循环中添加一个标签(名称):
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.
它在 10g 中不可用,但它是11G 中的新功能
您能否将 IF 重构为一个函数,并在适当的位置返回(必要时提前)。然后控制流将在正确的位置进入循环。
那有意义吗?
不完全优雅,但简单:
DECLARE
done BOOLEAN;
BEGIN
FOR i IN 1..50 LOOP
IF done THEN
NULL;
ELSE
<do loop stuff>;
END IF;
END LOOP;
END;
在 Oracle 中,有一个类似的语句称为 EXIT,它要么退出循环,要么退出函数/过程(如果没有要退出的循环)。您可以添加一个 WHEN 来检查某些条件。
您可以将上面的示例重写如下:
DECLARE
done BOOLEAN;
BEGIN
FOR i IN 1..50 LOOP
EXIT WHEN done;
END LOOP;
END;
如果您想从一些嵌套循环和逻辑的深处退出,这可能还不够,但比几个 GOTO 和 NULL 更清晰。
这并不完全是问题的答案,但值得注意的是:
continue
PL/SQL 和所有其他以相同方式使用它的编程语言中的语句很容易被误解。
如果编程语言开发人员skip
改为调用关键字,会更明智、更清晰、更简洁。
对我来说,有 C、C++、Python 的背景……一直很清楚“继续”是什么意思。
但是如果没有那个历史背景,你可能会结束对这段代码的解释
for i in .. tab_xy.count loop
CONTINUE WHEN some_condition(tab_xy(i));
do_process(tab_xy(i));
end loop;
像这样:
循环遍历表 tab_xy 的记录。
如果记录满足 some_condition 则继续,否则忽略此记录。
Do_process 记录。
这种解释是完全错误的,但是如果您将 PL/SQL 代码想象成一种烹饪收据并大声朗读,就会发生这种情况。
事实上,就在昨天,它发生在一位经验丰富的开发同事身上。