SET SERVEROUTPUT ON
BEGIN
<<outer_loop>>
FOR i IN 1..10 LOOP
FOR i IN 1..3 LOOP
EXIT outer_loop WHEN outer_loop.i = 3;
DBMS_OUTPUT.PUT_LINE('outer i is:' || outer_loop.i || ' inner i is: ' ||i);
GOTO goodbye;
END LOOP;
END LOOP;
<<goodbye>>
NULL;
END;
/
我有上面的代码,它给出了下面的结果,但我的笔记说永远不要这样做。为什么会这样呢?毕竟它确实有效。
anonymous block completed
outer i is:1 inner i is: 1
几乎在所有语言中都不鼓励使用
GOTO
,主要是因为它会损害代码的可读性,是的,在你的情况下更糟糕 - 你正在跳过两层堆栈。
除此之外,PL/SQL 还有这个简洁的 labels 功能。它很少有用,但代码中的符号正是用于此目的。
假设您有两个这样嵌套的循环。
BEGIN
<<outer>>
FOR i IN 1..2 LOOP
<<inner>>
FOR j IN 1..2 LOOP
dbms_output.put_line('In inner loop');
END LOOP;
dbms_output.put_line('In outer loop');
END LOOP;
dbms_output.put_line('Finished');
END;
显然,输出将是
In inner loop
In inner loop
In outer loop
In inner loop
In inner loop
In outer loop
Finished
有时您需要在“正常”完成之前退出循环,因此您添加
EXIT;
。
BEGIN
<<outer>>
FOR i IN 1..2 LOOP
<<inner>>
FOR j IN 1..2 LOOP
dbms_output.put_line('In inner loop');
EXIT;
END LOOP;
dbms_output.put_line('In outer loop');
END LOOP;
dbms_output.put_line('Finished');
END;
这会导致外循环的每次迭代只执行一次嵌套循环。
In inner loop
In outer loop
In inner loop
In outer loop
Finished
但是您可能根本想中止处理,为此您可以在嵌套循环中设置一些标志变量并在外循环中检查其值,或者您可以指定要退出的循环。
BEGIN
<<outer>>
FOR i IN 1..2 LOOP
<<inner>>
FOR j IN 1..2 LOOP
dbms_output.put_line('In inner loop');
EXIT outer;
END LOOP;
dbms_output.put_line('In outer loop');
END LOOP;
dbms_output.put_line('Finished');
END;
这样你就退出了两个循环。
In inner loop
Finished
回到您的示例,如果消除 GOTO,您将在内循环的第三次迭代中退出两个循环。
我不会说这对可读性很有好处,我宁愿以某种方式通知外循环一些特殊的东西,而不是让内循环负责从外循环退出。
GOTO 被认为是糟糕的编程实践。它来自旧时代,当时旧的编程语言没有太多的结构,程序员被迫使用大量的 GOTO。
GOTO 会导致所谓的意大利面条代码。 读起来很难,也很难 明白了。