【问题标题】:'CONTINUE' keyword in Oracle 10g PL/SQLOracle 10g PL/SQL 中的“CONTINUE”关键字
【发布时间】:2010-09-15 17:15:43
【问题描述】:

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

我听说 Oracle 11g 有这个作为一个新特性,但不幸的是升级不是一个选项。

在 10g 中是否有任何替代 CONTINUE 的方法?我认为将 SP 的逻辑重构为一种变通方法是不切实际的,因为我有一个外部循环、一个 IF,然后是一个嵌套的 IF,然后是该 IF 中语句块末尾的 CONTINUE。

任何帮助将不胜感激,干杯。

【问题讨论】:

    标签: oracle continue


    【解决方案1】:

    这并不完全是问题的答案,但值得注意:

    PL/SQL 中的continue 语句和所有其他以相同方式使用它的编程语言很容易被误解。

    如果编程语言开发人员改为使用关键字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 代码想象成一种烹饪收据并大声读出来,这可能会发生。

    事实上,就在昨天,一位经验丰富的开发同事遇到了这种情况。

    【讨论】:

    • 我完全同意你的看法。我一直认为continue应该改成skip。
    【解决方案2】:

    为了以后的搜索,他们在 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.
    

    【讨论】:

      【解决方案3】:

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

      【讨论】:

      • 只是比 GOTO 后跟 NULL 行丑一点,但它有效。谢谢!
      【解决方案4】:

      不完全优雅,但简单:

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

      【讨论】:

        【解决方案5】:

        虽然它有点复杂而且只是假的,但你可以这样使用异常:

        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;
        

        【讨论】:

          【解决方案6】:

          它在 10g 中不可用,但它在 11G 中是 new feature

          【讨论】:

            【解决方案7】:

            在 Oracle 中有一个类似的语句,称为 EXIT,它要么退出循环,要么退出函数/过程(如果没有要退出的循环)。您可以添加 WHEN 来检查某些条件。

            你可以将上面的例子改写如下:

            DECLARE
               done  BOOLEAN;
            BEGIN
                FOR i IN 1..50 LOOP
                 EXIT WHEN done;
               END LOOP;
            END;
            

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

            【讨论】:

            • EXIT 解决方案在这种情况下实际上不起作用,因为它会终止整个循环,而不是像 CONTINUE 那样在下一次迭代中开始。我想我将不得不使用 GOTO 解决方案,为大家的建议喝彩!
            【解决方案8】:

            您可以使用goto and 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;
            

            【讨论】:

            • 有时,我们只需要输入它,然后捂住鼻子。 :)
            • 您也可以使用完美模仿 continue 的构造。并且不添加任何 null :) 请参阅下面的回复。
            • 正如下面的答案所暗示的 (@Thorsten),我认为您可能正在寻找 EXIT。
            【解决方案9】:

            您能否将 IF 重构为一个函数,并在适当的位置返回(必要时提前)。然后控制流将在正确的位置循环。

            这有意义吗?

            【讨论】:

              猜你喜欢
              • 1970-01-01
              • 1970-01-01
              • 1970-01-01
              • 1970-01-01
              • 1970-01-01
              • 1970-01-01
              • 1970-01-01
              • 1970-01-01
              • 2019-06-26
              相关资源
              最近更新 更多