GOTO语句

GOTO语句可以实现从GOTO位置到目标语句的无条件跳转。GOTO语句会改变原本的执行逻辑,因此应该慎重使用,或者也可以使用EXCEPTION处理特殊场景。当执行GOTO语句时,目标Label必须是唯一的。

语法

label declaration ::=

GOTO语句 - 图1

goto statement ::=

GOTO语句 - 图2

示例

  1. openGauss=# CREATE OR REPLACE PROCEDURE GOTO_test()
  2. AS
  3. DECLARE
  4. v1 int;
  5. BEGIN
  6. v1 := 0;
  7. LOOP
  8. EXIT WHEN v1 > 100;
  9. v1 := v1 + 2;
  10. if v1 > 25 THEN
  11. GOTO pos1;
  12. END IF;
  13. END LOOP;
  14. <<pos1>>
  15. v1 := v1 + 10;
  16. raise info 'v1 is %. ', v1;
  17. END;
  18. /
  19. call GOTO_test();

限制场景

GOTO使用有以下限制场景:

  • 不支持有多个相同的GOTO labels目标场景,无论是否在同一个block中。

    1. BEGIN
    2. GOTO pos1;
    3. <<pos1>>
    4. SELECT * FROM ...
    5. <<pos1>>
    6. UPDATE t1 SET ...
    7. END;
  • 不支持GOTO跳转到IF语句、CASE语句、LOOP语句中。

    1. BEGIN
    2. GOTO pos1;
    3. IF valid THEN
    4. <<pos1>>
    5. SELECT * FROM ...
    6. END IF;
    7. END;
  • 不支持GOTO语句从一个IF子句跳转到另一个IF子句,或从一个CASE语句的WHEN子句跳转到另一个WHEN子句。

    1. BEGIN
    2. IF valid THEN
    3. GOTO pos1;
    4. SELECT * FROM ...
    5. ELSE
    6. <<pos1>>
    7. UPDATE t1 SET ...
    8. END IF;
    9. END;
  • 不支持从外部块跳转到内部的BEGIN-END块。

    1. BEGIN
    2. GOTO pos1;
    3. BEGIN
    4. <<pos1>>
    5. UPDATE t1 SET ...
    6. END;
    7. END;
  • 不支持从异常处理部分跳转到当前的BEGIN-END块。但可以跳转到上层BEGIN-END块。

    1. BEGIN
    2. <<pos1>>
    3. UPDATE t1 SET ...
    4. EXCEPTION
    5. WHEN condition THEN
    6. GOTO pos1;
    7. END;
  • 如果从GOTO到一个不包含执行语句的位置,需要添加NULL语句。

    1. DECLARE
    2. done BOOLEAN;
    3. BEGIN
    4. FOR i IN 1..50 LOOP
    5. IF done THEN
    6. GOTO end_loop;
    7. END IF;
    8. <<end_loop>> -- not allowed unless an executable statement follows
    9. NULL; -- add NULL statement to avoid error
    10. END LOOP; -- raises an error without the previous NULL
    11. END;
    12. /