lightdb plorasql支持goto命令

背景

GOTO语句是一个无条件的跳转语句,可以将程序的执行流程跳转到某个标签指定位置。 标签必须在其执行范围内是唯一的。在LightDB Database 23.2版本中plorasql对GOTO语句进行了支持。

场景

plorasql中匿名块、FUNCTION、PROCEDURE中支持GOTO语句.
但是GOTO的使用存在如下限制

  • 指定跳转位置的标签必须定义于一个可以执行的语句或PL/oraSQL块之前。
  • 可以从嵌套块跳转到外部块,但不能从外层块跳转到嵌套块。
  • 不能从IF语句外部跳到IF语句内部。
  • 不能从循环体外跳到循环体内。
  • 不能从子程序外部跳到子程序内部。
  • 不能从CASE语句外跳转到CASE语句内。
  • 不能从异常处理部分跳转到可执行部分,也不能从可执行部分跳到异常处理部分。

案例演示

以下案例使用ltsql命令可以执行运行。

创建oracle环境

create database test_oracle lightdb_syntax_compatible_type oracle;

连接 test_oracle数据库

\c test_oracle

设置output输出

select dbms_output.serveroutput(true);

嵌套BLOCK

goto不支持从外部block GOTO到内部block,如下案例:

BEGIN
  DBMS_OUTPUT.PUT_LINE('out block 1');
  goto testlabel;
  DBMS_OUTPUT.PUT_LINE('out block 2');
  BEGIN
    DBMS_OUTPUT.PUT_LINE('in block 1');
    <<testlabel>>
    DBMS_OUTPUT.PUT_LINE('in block 2');
  END;
  DBMS_OUTPUT.PUT_LINE('out block 3');
END;
/

输出结果如下:

out block 1
ERROR:  illegal GOTO statement; this GOTO cannot branch to label "testlabel"
CONTEXT:  PL/oraSQL function inline_code_block

goto支持从内部block GOTO到外部block,如下案例:

BEGIN
  DBMS_OUTPUT.PUT_LINE('out block 1');
  goto testlabel;
  DBMS_OUTPUT.PUT_LINE('out block 2');
  <<testlabel>>
  BEGIN
    DBMS_OUTPUT.PUT_LINE('in block 1');
    goto testlabel2;
    DBMS_OUTPUT.PUT_LINE('in block 2');
  END;

  DBMS_OUTPUT.PUT_LINE('out block 3');

  <<testlabel2>>
  DBMS_OUTPUT.PUT_LINE('out block 4');
END;
/

输出结果如下:

out block 1
in block 1
out block 4
DO

LOOP

goto不支持从外部GOTO到LOOP内部,如下案例:

BEGIN 
    DBMS_OUTPUT.PUT_LINE('OUT LOOP 1');
    goto testlabel;
    LOOP
        DBMS_OUTPUT.PUT_LINE('IN LOOP 1');
        <<testlabel>>
        DBMS_OUTPUT.PUT_LINE('IN LOOP 2');
    END LOOP;
    DBMS_OUTPUT.PUT_LINE('OUT LOOP 2');
END;
/

输出结果如下:

OUT LOOP 1
ERROR:  illegal GOTO statement; this GOTO cannot branch to label "testlabel"
CONTEXT:  PL/oraSQL function inline_code_block

goto支持从LOOP内部GOTO到外部,如下案例:

BEGIN
    DBMS_OUTPUT.PUT_LINE('OUT LOOP 1');
    goto testlabel;
    DBMS_OUTPUT.PUT_LINE('OUT LOOP 2');
    <<testlabel>>
    LOOP
        DBMS_OUTPUT.PUT_LINE('IN LOOP 1');
        goto testlabel2;
        DBMS_OUTPUT.PUT_LINE('IN LOOP 2');
    END LOOP;
    DBMS_OUTPUT.PUT_LINE('OUT LOOP 3');
    <<testlabel2>>
    DBMS_OUTPUT.PUT_LINE('OUT LOOP 4');
END;
/

输出结果如下:

OUT LOOP 1
IN LOOP 1
OUT LOOP 4
DO

WHILE

goto不支持从外部GOTO到WHILE内部,如下案例:

BEGIN 
    DBMS_OUTPUT.PUT_LINE('OUT LOOP 1');
    goto testlabel;
    WHILE true LOOP
        DBMS_OUTPUT.PUT_LINE('IN LOOP 1');
        <<testlabel>>
        DBMS_OUTPUT.PUT_LINE('IN LOOP 2');
    END LOOP;
    DBMS_OUTPUT.PUT_LINE('OUT LOOP 2');
END;
/

输出结果如下:

OUT LOOP 1
ERROR:  illegal GOTO statement; this GOTO cannot branch to label "testlabel"
CONTEXT:  PL/oraSQL function inline_code_block

goto支持从WHILE内部GOTO到外部,如下案例:

BEGIN 
    DBMS_OUTPUT.PUT_LINE('OUT LOOP 1');
    goto testlabel;
    DBMS_OUTPUT.PUT_LINE('OUT LOOP 2');

    <<testlabel>>
    WHILE true LOOP
        DBMS_OUTPUT.PUT_LINE('IN LOOP 1');
        goto testlabel2;
        DBMS_OUTPUT.PUT_LINE('IN LOOP 2');
    END LOOP;
    DBMS_OUTPUT.PUT_LINE('OUT LOOP 3');
    <<testlabel2>>
    DBMS_OUTPUT.PUT_LINE('OUT LOOP 4');
END;
/

输出结果如下:

OUT LOOP 1
IN LOOP 1
OUT LOOP 4
DO

FOR

goto不支持从外部block GOTO到FOR内部,如下案例:

DECLARE 
    i INTEGER;
BEGIN 
    DBMS_OUTPUT.PUT_LINE('OUT LOOP 1');
    goto testlabel;
    FOR i IN 1..10 LOOP
        DBMS_OUTPUT.PUT_LINE('IN LOOP 1');
        <<testlabel>>
        DBMS_OUTPUT.PUT_LINE('IN LOOP 2');
    END LOOP;
    DBMS_OUTPUT.PUT_LINE('OUT LOOP 2');
END;
/

输出结果如下:

OUT LOOP 1
ERROR:  illegal GOTO statement; this GOTO cannot branch to label "testlabel"
CONTEXT:  PL/oraSQL function inline_code_block

goto支持从内部FOR GOTO到外部block,如下案例:

DECLARE
    i INTEGER;
BEGIN 
    DBMS_OUTPUT.PUT_LINE('OUT LOOP 1');
    goto testlabel;
    DBMS_OUTPUT.PUT_LINE('OUT LOOP 2');

    <<testlabel>>
    FOR i IN 1..10 LOOP
        DBMS_OUTPUT.PUT_LINE('IN LOOP 1');
        goto testlabel2;
        DBMS_OUTPUT.PUT_LINE('IN LOOP 2');
    END LOOP;
    DBMS_OUTPUT.PUT_LINE('OUT LOOP 3');
    <<testlabel2>>
    DBMS_OUTPUT.PUT_LINE('OUT LOOP 4');
END;
/ 

输出结果如下:

OUT LOOP 1
IN LOOP 1
OUT LOOP 4
DO

COMMIT

goto支持GOTO到COMMIT,如下案例:

CREATE TABLE test1(a int);

BEGIN
    INSERT INTO test1 (a) VALUES (1);
    INSERT INTO test1 (a) VALUES (2);
    goto testlabel;
    INSERT INTO test1 (a) VALUES (3);
    <<testlabel>>
    COMMIT;
END;
/
select * from test1;
DROP TABLE test1;

输出结果如下:


DO
lightdb@postgres=# select * from test1;
 a 
---
 1
 2
(2 rows)


ROLLBACK

goto支持GOTO到rollback,如下案例:

CREATE TABLE test1(a int);

BEGIN
    INSERT INTO test1 (a) VALUES (1);
    INSERT INTO test1 (a) VALUES (2);
    goto testlabel;
    INSERT INTO test1 (a) VALUES (3);
    <<testlabel>>
    ROLLBACK;
END;
/

select * from test1;
DROP TABLE test1;

输出结果如下:


a 
---
(0 rows)
DROP TABLE test1;

IF

goto不支持从外部block GOTO到IF内部block,如下案例:

BEGIN
  DBMS_OUTPUT.PUT_LINE('out block 1');
  goto testlabel;
  DBMS_OUTPUT.PUT_LINE('out block 2');
  IF true THEN 
    DBMS_OUTPUT.PUT_LINE('in block 1');
    <<testlabel>>
    DBMS_OUTPUT.PUT_LINE('in block 2');
  END IF;

  DBMS_OUTPUT.PUT_LINE('out block 3');
END;
/

输出结果如下:

out block 1
ERROR:  illegal GOTO statement; this GOTO cannot branch to label "testlabel"
CONTEXT:  PL/oraSQL function inline_code_block

goto支持从IF内部block GOTO到外部block,如下案例:

BEGIN
  DBMS_OUTPUT.PUT_LINE('out block 1');
  goto testlabel;
  DBMS_OUTPUT.PUT_LINE('out block 2');
  <<testlabel>>
  IF true THEN
    DBMS_OUTPUT.PUT_LINE('in block 1');
    goto testlabel2;
    DBMS_OUTPUT.PUT_LINE('in block 2');
  END IF;

  DBMS_OUTPUT.PUT_LINE('out block 3');

  <<testlabel2>>
  DBMS_OUTPUT.PUT_LINE('out block 4');
END;
/

输出结果如下:

out block 1
in block 1
out block 4
DO

CASE

goto不支持从外部block GOTO到CASE内部block,如下案例:

BEGIN
  DBMS_OUTPUT.PUT_LINE('out block 1');
  goto testlabel;
  DBMS_OUTPUT.PUT_LINE('out block 2');
  
  CASE 2 
    WHEN 1 THEN
      <<testlabel>>
      DBMS_OUTPUT.PUT_LINE('in block 1');
    ELSE 
      DBMS_OUTPUT.PUT_LINE('in block 2');
  END CASE;
  DBMS_OUTPUT.PUT_LINE('out block 3');
END;
/

输出结果如下:

out block 1
ERROR:  illegal GOTO statement; this GOTO cannot branch to label "testlabel"
CONTEXT:  PL/oraSQL function inline_code_block

goto支持从CASE内部block GOTO到外部block,如下案例:

BEGIN
  DBMS_OUTPUT.PUT_LINE('out block 1');
  goto testlabel;
  DBMS_OUTPUT.PUT_LINE('out block 2');
  <<testlabel>>
  
  CASE 2 
    WHEN 1 THEN
      DBMS_OUTPUT.PUT_LINE('in block 1');
    ELSE 
      DBMS_OUTPUT.PUT_LINE('in block 2');
      goto testlabel2;
      DBMS_OUTPUT.PUT_LINE('in block 3');
  END CASE;

  DBMS_OUTPUT.PUT_LINE('out block 3');

  <<testlabel2>>
  DBMS_OUTPUT.PUT_LINE('out block 4');
END;
/

输出结果如下:

out block 1
in block 2
out block 4
DO

EXIT

goto支持GOTO到EXIT,如下案例:

BEGIN
  DBMS_OUTPUT.PUT_LINE('out block 1');
  LOOP 
    goto testlabel;
    DBMS_OUTPUT.PUT_LINE('out block 2');
    <<testlabel>>
    EXIT;
  END LOOP;
  DBMS_OUTPUT.PUT_LINE('out block 3');
END;
/

输出结果如下:

out block 1
out block 3
DO

RETURN

goto支持GOTO到RETURN,如下案例:

BEGIN
  DBMS_OUTPUT.PUT_LINE('out block 1');
  LOOP
    goto testlabel;
    DBMS_OUTPUT.PUT_LINE('in block 1');
    <<testlabel>>
    RETURN;
  END LOOP;
  DBMS_OUTPUT.PUT_LINE('out block 2');
END;
/

输出结果如下:

out block 1
DO

GOTO

goto支持GOTO到GOTO,如下案例:

BEGIN
  goto testlabel;
  DBMS_OUTPUT.PUT_LINE('out block 1');
  <<testlabel>> 
  goto testlabel3;
  <<testlabel2>>
  DBMS_OUTPUT.PUT_LINE('out block 2');
  <<testlabel3>>
  DBMS_OUTPUT.PUT_LINE('out block 3');
  <<testlabel4>>
  DBMS_OUTPUT.PUT_LINE('out block 4');
END;
/

输出结果如下:

out block 3
out block 4
DO

EXCEPTION

goto不支持从正常块与异常块相互GOTO,如下案例:

不支持从异常块GOTO到正常块。

DECLARE 
  i INTEGER ;
BEGIN
  DBMS_OUTPUT.PUT_LINE('block 1');
  i := 1/0;
<<testlabel>> 
  DBMS_OUTPUT.PUT_LINE('block 2');
EXCEPTION
    WHEN others THEN 
      DBMS_OUTPUT.PUT_LINE('exception block 1'); 
      goto testlabel;
      DBMS_OUTPUT.PUT_LINE('exception block 2'); 
END;
/

输出结果如下:

block 1
exception block 1
ERROR:  illegal GOTO statement; this GOTO cannot branch to label "testlabel"
CONTEXT:  PL/oraSQL function inline_code_block

也不支持从正常块GOTO到异常块

DECLARE 
  i INTEGER ;
BEGIN
  DBMS_OUTPUT.PUT_LINE('1');
  goto testlabel;
EXCEPTION  
  WHEN others THEN
      <<testlabel>>
      DBMS_OUTPUT.PUT_LINE('2');
      return ;
END; 
/

输出结果如下:

1
ERROR:  illegal GOTO statement; this GOTO cannot branch to label "testlabel"
CONTEXT:  PL/oraSQL function inline_code_block

NULL

支持GOTO到NULL,如下示例:

BEGIN
    DBMS_OUTPUT.PUT_LINE('STEP 1');
    GOTO testlabel;
    DBMS_OUTPUT.PUT_LINE('STEP 2');
    <<testlabel>>
    NULL;
    DBMS_OUTPUT.PUT_LINE('STEP 3');
END;
/

输出结果如下:

STEP 1
STEP 3
DO

结论

上面示例中演示了匿名块中的GOTO,plorasql函数(FUNCTION)与plorasql存储过程(PROCEDURE)也同样适用,值得注意的是,plorasql 23.2版本FUNCTION中还不支持事务,所以不能在FUNCTION中GOTO到COMMMIT/ROLLBACK。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值