Oracle 10g PL/SQL中的'CONTINUE'关键字

41

我正在将一个 TSQL 存储过程迁移到 PL/SQL,但遇到了一个问题 - Oracle 10g 中缺少 CONTINUE 关键字。

我读到 Oracle 11g 有这个新功能,但不幸的是升级不是一个选项。

在 10g 中是否有 CONTINUE 的替代方法?我认为重构存储过程的逻辑作为一种解决方法并不实际,因为我有一个外部循环,一个 IF,然后一个嵌套的 IF,在该 IF 的语句块末尾有 CONTINUE。

非常感谢任何帮助。谢谢。

9个回答

59

你可以使用 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;

4
有时候,我们只需要将其输入并在之后捂住鼻子。 :) - jop
您还可以使用一个类似于 continue 的结构,而且不需要添加任何 null :) 请查看下面的回复。 - Sylvain Rodrigue
正如下面的答案所建议的那样(@Thorsten),我认为你可能正在寻找EXIT。 - OverMars

12

虽然有点复杂且只是一个假的例子,但你可以这样使用异常:

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;

非常感谢,我一直在寻找如何在FOR循环中处理异常,你解决了我的问题!在额外的BEGIN ... END块中添加逻辑解决了我的问题! - Jane Kathambi

7
事实上,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;

1
比GOTO后面跟着NULL行要好看一点,但它能用。谢谢! - Tom Wayson

6

在 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.

5

10g版本中不支持此功能,但在11G中推出了新特性


4

你能否将这些IF语句重构为一个函数,并在适当的位置返回(必要时尽早返回)。然后控制流会在循环的正确位置继续。

这样说你明白了吗?


2

虽然不太优雅,但很简单:

DECLARE
   done  BOOLEAN;
BEGIN
   FOR i IN 1..50 LOOP
      IF done THEN
         NULL;
      ELSE
         <do loop stuff>;
      END IF;
   END LOOP; 
END;

1
在Oracle中有一个类似的语句叫做EXIT,它可以退出循环或函数/过程(如果没有循环可退出)。您可以添加WHEN来检查某些条件。
您可以将上面的示例重写如下:
DECLARE
   done  BOOLEAN;
BEGIN
    FOR i IN 1..50 LOOP
     EXIT WHEN done;
   END LOOP;
END;

如果你想要从一些嵌套的循环和逻辑中退出,这可能不够用,但比几个GOTO和NULL更清晰。


1
EXIT 方案在这种情况下并不适用,因为它会终止整个循环,而不是像 CONTINUE 那样只是从下一次迭代开始。我想我必须采取 GOTO 的解决方案,感谢大家的建议! - Chris McAtackney

1
这并不是问题的确切答案,但仍值得注意:PL/SQL和其他使用相同方式的编程语言中的continue语句很容易被误解。如果编程语言开发人员将关键字称为skip,那么会更加明晰简洁。对于我而言,有C、C++、Python等背景,'continue'的含义一直很清晰。但如果没有这种历史背景,你可能会错误地解释这段代码。
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代码想象成一种烹饪配方并大声朗读,这种情况可能会发生。

事实上,昨天发生在一个非常有经验的开发同事身上。


我完全同意你的观点。我一直认为continue应该改成skip。 - Stack0verflow

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接