“继续” Oracle 10g PL/SQL 中的关键字

发布于 2024-07-07 08:27:23 字数 262 浏览 10 评论 0原文

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

我读到 Oracle 11g 将此作为一项新功能,但不幸的是,升级不是一个选择。

10g 中是否还有 CONTINUE 的替代方案? 我认为重构 SP 的逻辑作为解决方法是不切实际的,因为我有一个外循环、一个 IF,然后是一个嵌套 IF,然后是该 IF 内语句块末尾的 CONTINUE。

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

I'm migrating a TSQL stored procedure to PL/SQL and have encountered a problem - the lack of a CONTINUE keyword in Oracle 10g.

I've read that Oracle 11g has this as a new feature, but upgrading is not an option unfortunately.

Is there any alternative to CONTINUE in 10g? I don't believe it's practical to restructure the logic of the SP as a work-around, because I have an outer loop, an IF, then a nested IF, then the CONTINUE at the end of a statement block within that IF.

Any help would be greatly appreciated, cheers.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(9

只有影子陪我不离不弃 2024-07-14 08:27:25

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

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 代码想象成一种烹饪收据并大声朗读,这种情况就可能发生。

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

This isn't exactly an answer to the question, but nevertheless worth noting:

The continue statement in PL/SQL and all other programming languages which use it the same way, can easily be misunderstood.

It would have been much wiser, clearer and more concise if the programming language developers had called the keyword skip instead.

For me, with a background of C, C++, Python, ... it has always been clear what `continue' means.

But without that historical background, you might end intepreting this code

for i in .. tab_xy.count loop
    CONTINUE WHEN some_condition(tab_xy(i));
    do_process(tab_xy(i));
end loop;

like this:

Loop through the records of the table tab_xy.

Continue if the record fulfills some_condition, otherwise ignore this record.

Do_process the record.

This interpretation is completely wrong, but if you imagine the PL/SQL code as a kind of cooking receipt and read it aloud, this can happen.

In fact it happened to a very experienced development co-worker just yesterday.

破晓 2024-07-14 08:27:24

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

In fact, PL SQL does have something to replace CONTINUE. All you have to do is to add a label (a name) to the loop :

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;
苍景流年 2024-07-14 08:27:24

为了将来的搜索,在 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.

For future searches, in oracle 11g they added a continue statement, which can be used like this :

    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.
关于从前 2024-07-14 08:27:24

它在 10g 中不可用,但它是 11G 中的新功能

It's not available in 10g, however it's a new feature in 11G

冷情 2024-07-14 08:27:24

您能否将 IF 重构为函数,在适当的点返回(如果需要的话,尽早返回)。 然后控制流将在正确的位置进入循环。

那有意义吗?

Can you refactor the IFs into a function, returning at the appropriate point (early if necessary). Then the control flow will pick up in the loop at the right place.

Does that make sense?

女中豪杰 2024-07-14 08:27:24

不完全优雅,但很简单:

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

Not exactly elegant, but simple:

DECLARE
   done  BOOLEAN;
BEGIN
   FOR i IN 1..50 LOOP
      IF done THEN
         NULL;
      ELSE
         <do loop stuff>;
      END IF;
   END LOOP; 
END;
暗藏城府 2024-07-14 08:27:24

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

您可以将上面的示例重写如下:

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

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

In Oracle there is a similar statement called EXIT that either exits a loop or a function/procedure (if there is no loop to exit from). You can add a WHEN to check for some condition.

You could rewrite the above example as follows:

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

This may not be enough if you want to exit from deep down some nested loops and logic, but is a lot clearer than a couple of GOTOs and NULLs.

梦亿 2024-07-14 08:27:23

您可以使用转到和标签来模拟继续。

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;

You can simulate a continue using 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;
清风夜微凉 2024-07-14 08:27:23

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

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;

Though it's a bit complex and just a fake, you can use exception this way :

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;
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文