• Oracle的学习心得和知识总结(八)|Oracle数据库PL/SQL语言GOTO语句技术详解


    注:提前言明 本文借鉴了以下博主、书籍或网站的内容,其列表如下:

    1、参考书籍:《Oracle Database SQL Language Reference》
    2、参考书籍:《PostgreSQL中文手册》
    3、EDB Postgres Advanced Server User Guides,点击前往
    4、PostgreSQL数据库仓库链接,点击前往
    5、PostgreSQL中文社区,点击前往
    6、Oracle数据库 5.3 Sequential Control Statements 官方文档说明,点击前往
    7、Oracle数据库 GOTO Statement 官方文档说明,点击前往
    8、EDB数据库 GOTO statement v14官方文档说明,点击前往


    1、本文内容全部来源于开源社区 GitHub和以上博主的贡献,本文也免费开源(可能会存在问题,评论区等待大佬们的指正)
    2、本文目的:开源共享 抛砖引玉 一起学习
    3、本文不提供任何资源 不存在任何交易 与任何组织和机构无关
    4、大家可以根据需要自行 复制粘贴以及作为其他个人用途,但是不允许转载 不允许商用 (写作不易,还请见谅 💖)
    5、本文仅适于从事于PostgreSQL数据库内核开发者和数据库爱好者,对普通读者而言难度较大 但对于希望从事于数据库内核开发的初学者来说,是一次机会十分难得的学习案例 💪
    6、本文内容基于PostgreSQL15.0源码开发而成




    本人博客严正声明

    是这样的,熟悉在下的小伙伴们都知道 我写博客主要目的就是分享和学习总结。至于CSDN的排名 排名什么的,我并不是很在意!

    • 一来 很不喜欢标题党
    • 二来 更反感灌些水文
    • 三来 痛恨无下限抄袭

    本人博客都是认认真真写的,结果在CSDN并没有什么的太大的名气 关注度什么的也不高!前些天 一位好心的粉丝私聊了在下,反而一名某平台的哥们儿 快把我的《PostgreSQL的学习心得和知识总结》都给照搬过去了,甚至一个字都不改(连同在下 都是只字不提 好歹稍微提一下呀)!!!

    实在是太过分,后来经过(友好)协商,现已经全部删除了!

    本人是做PostgreSQL内核开发的,深感当下学风不正 大家都很浮躁,一向踏踏实实深耕的并不是很多!因为写代码这件事情上,欺骗不了任何人!本本分分老老实实地写好代码做好学问十分不易,容不得掺沙子和造假!这里把我喜欢的一句话送给各位以共勉:

    非淡泊无以明志,
    非宁静无以致远!


    文章快速说明索引

    学习目标:

    目的:接下来这段时间我想做一些兼容Oracle数据库PL/SQL语言上的一些功能开发,本专栏这里主要是学习以及介绍Oracle数据库功能的使用场景、原理说明和注意事项等,基于PostgreSQL数据库的功能开发等之后 由新博客进行介绍和分享!今天我们主要看一下 PL/SQL语言GOTO语句 的相关内容!


    学习内容:(详见目录)

    1、Oracle数据库PL/SQL语言 顺序控制语句之GOTO和NULL语句


    学习时间:

    2022-11-29 10:25:10


    学习产出:

    1、Oracle数据库PL/SQL语言 顺序控制语句之GOTO和NULL语句
    2、CSDN 技术博客 1篇


    注:下面我们所有的学习环境是Centos7+PostgreSQL15.0+Oracle19c+MySQL5.7

    postgres=# select version();
                                       version                                   
    -----------------------------------------------------------------------------
     PostgreSQL 15.0 on x86_64-pc-linux-gnu, compiled by gcc (GCC) 7.1.0, 64-bit
    (1 row)
    
    postgres=#
    
    #-----------------------------------------------------------------------------#
    
    SQL> select * from v$version;          
    
    BANNER        Oracle Database 19c EE Extreme Perf Release 19.0.0.0.0 - Production	
    BANNER_FULL	  Oracle Database 19c EE Extreme Perf Release 19.0.0.0.0 - Production Version 19.17.0.0.0	
    BANNER_LEGACY Oracle Database 19c EE Extreme Perf Release 19.0.0.0.0 - Production	
    CON_ID 0
    
    
    #-----------------------------------------------------------------------------#
    
    mysql> select version();
    +-----------+
    | version() |
    +-----------+
    | 5.7.19    |
    +-----------+
    1 row in set (0.06 sec)
    
    mysql>
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29

    顺序控制语句说明

    与IF和LOOP语句不同,顺序控制语句GOTO和NULL对于PL/SQL编程并不重要。很少需要GOTO语句,它指向一个指定的语句。偶尔,它会简化逻辑,以保证它的使用。NULL语句什么都不做,它可以通过明确条件语句的含义和操作来提高可读性。

    • GOTO子句:GOTO语句无条件地将控制权转移到标签。标签在其作用域中必须是唯一的,并且必须在可执行语句或PL/SQL块之前。运行时,GOTO语句将控制权转移到标记语句或块。有关GOTO语句的限制,下面详细说明。谨慎使用GOTO语句——过度使用会导致代码难以理解和维护。不要使用GOTO语句将控制从深度嵌套结构转移到异常处理程序。相反,抛出一个异常。有关PL/SQL异常处理机制的信息,请参见PL/SQL错误处理。GOTO语句将控制转移到出现引用标签的第一个封闭块。

    • NULL子句:NULL语句只将控制权传递给下一个语句。有些语言将这样的指令称为no-op(无操作)。

    NULL语句的一些用法是:

    1. 为GOTO语句提供一个目标
    2. 通过明确条件语句的含义和作用来提高可读性
    3. 创建占位符和存根子程序
    4. 表示你意识到某种可能性,但不需要采取任何行动

    GOTO语句的说明

    GOTO 语句将控制转移到带标签的块或语句,即:该语句使执行点跳转到具有指定标签的语句。


    GOTO 语句的限制如下:

    如果 GOTO 语句过早地退出游标 FOR LOOP 语句,游标将关闭。

    • GOTO 语句不能将控制转移到 IF 语句、CASE 语句、LOOP 语句或子块中
    • GOTO 语句不能将控制从一个 IF 语句子句转移到另一个,或从一个 CASE 语句 WHEN 子句转移到另一个
    • GOTO 语句不能将控制转移出子程序
    • GOTO 语句无法将控制转移到异常处理程序中
    • GOTO 语句无法将控制从异常处理程序转移回当前块(但它可以将控制从异常处理程序转移到封闭块 即:父块)
    • GOTO 语句不能将控制转移到条件块或子块中,但可以从条件块或子块中转移控制

    • GOTO 语句不能跳转到声明(declaration)
    • GOTO 语句不能将控制转移到另一个函数或过程中
    • 标签(label)不应放在块、函数或过程的末尾

    其语法格式如下:

    在这里插入图片描述

    GOTO <label>
    
    • 1

    标签:标识语句label 是分配给可执行语句或块的名称。在函数、过程或块的范围内必须是唯一的。要标记语句,请使用以下语法:

    <<label>> <statement>
    
    -- 其中 statement 是程序跳转到的执行点
    
    • 1
    • 2
    • 3

    如果 label 不在当前块中,则 GOTO 语句将控制转移到 label 出现的第一个封闭块。你可以标记(label)赋值语句、任何 SQL 语句和选定的过程语言语句。可以标记的过程语言语句有:

    -- EDB (V14)
    
    IF
    EXIT
    RETURN
    RAISE
    EXECUTE
    PERFORM
    GET DIAGNOSTICS
    OPEN
    FETCH
    MOVE
    CLOSE
    NULL
    COMMIT
    ROLLBACK
    GOTO
    CASE
    LOOP
    WHILE
    FOR
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21

    exit 被视为关键字,不能用作标签的名称。对应成语法如下:

    statement ::= <Assign_Statement>
     | <If_Statement>
     | <Loop_Statement>
     | <While_Statement>
     | <For_Statement>
     | <Goto_Statement> // 这就是我们这次要开发的
     | <Case_Statement>
     | <Exit_Statement>
     | <Return_Statement>
     | <Raise_Statement>
     | <Perform_Statement>
     | <Execute_Statement>
     | <Commit_Statement>
     | <RollBack_Statement>
     | <Close_Statement>
     | <Open_Statement>
     | <Fetch_Statement>
     | <Sql_Statement>
     | <Null_Statement> 
     | <Get_Diagnostics_Statement>
    
    -- 注:在PostgreSQL15中只会更多,详细请见:
    -- src/pl/plpgsql/src/pl_gram.y 的 proc_stmt
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23

    其使用案例如下:

    示例一:标签可以出现在语句之前:

    -- 判断一个数是否为素数
    
    SQL> set serveroutput on; 
    SQL> DECLARE
      p  VARCHAR2(30);
      n  PLS_INTEGER := 37;
    BEGIN
      FOR j in 2..ROUND(SQRT(n)) LOOP
        IF n MOD j = 0 THEN
          p := ' is not a prime number';
          GOTO print_now;
        END IF;
      END LOOP;
    
      p := ' is a prime number';
     
      <<print_now>> --here
      DBMS_OUTPUT.PUT_LINE(TO_CHAR(n) || p);
    END;
    /
      2    3    4    5    6    7    8    9   10   11   12   13   14   15   16   17  37 is a prime number
    
    PL/SQL procedure successfully completed.
    
    SQL>
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    SQL> DECLARE
      p  VARCHAR2(30);
      n  PLS_INTEGER := 64;
    BEGIN
      FOR j in 2..ROUND(SQRT(n)) LOOP
        IF n MOD j = 0 THEN
          p := ' is not a prime number';
          GOTO print_now;
        END IF;
      END LOOP;
    
      p := ' is a prime number';
     
      <<print_now>> --here
      DBMS_OUTPUT.PUT_LINE(TO_CHAR(n) || p);
    END;
    /
     
      2    3    4    5    6    7    8    9   10   11   12   13   14   15   16   17  64 is not a prime number
    
    PL/SQL procedure successfully completed.
    
    SQL>
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23

    示例二:标签只能出现在块之前或语句之前:

    SQL> DECLARE
      done  BOOLEAN;
    BEGIN
      FOR i IN 1..50 LOOP
        IF done THEN
           GOTO end_loop;
        END IF;
        <<end_loop>> --here
      END LOOP;
    END;
    /
     
      2    3    4    5    6    7    8    9   10   11    END LOOP;
      *
    ERROR at line 9:
    ORA-06550: line 9, column 3:
    PLS-00103: Encountered the symbol "END" when expecting one of the following:
    ( begin case declare exit for goto if loop mod null raise
    return select update while with <an identifier>
    <a double-quoted delimited-identifier> <a bind variable> <<
    continue close current delete fetch lock insert open rollback
    savepoint set sql execute commit forall merge pipe purge
    json_exists json_value json_query json_object json_array
    
    
    SQL>
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26

    示例三:标签可以出现在 NULL 语句之前:

    SQL> DECLARE
      done  BOOLEAN;
    BEGIN
      FOR i IN 1..50 LOOP
        IF done THEN
          GOTO end_loop;
        END IF;
        <<end_loop>> --here
        NULL;
      END LOOP;
    END;
    /
      2    3    4    5    6    7    8    9   10   11   12  
    PL/SQL procedure successfully completed.
    
    SQL>
    SQL> BEGIN
    	FOR i IN 1..50 LOOP
    		IF i = 30 THEN
    			GOTO end_loop;
    		END IF;
    	END LOOP;
    	<<end_loop>>
    	NULL;
    END;
    /
      2    3    4    5    6    7    8    9   10  
    PL/SQL procedure successfully completed.
    
    SQL>
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30

    示例四:GOTO 语句可以将控制权从当前块转移到封闭块。如下使用GOTO将分出一个环绕块:

    create table employees (employee_id number(6), last_name VARCHAR2(25));
    
    insert into employees values (120, 'Weiss');
    insert into employees values (121, 'Weiss1');
    insert into employees values (122, 'Weiss2');
    insert into employees values (123, 'Weiss3');
    insert into employees values (124, 'Weiss4');
    
    SQL> select * from employees;
    
    EMPLOYEE_ID LAST_NAME
    ----------- -------------------------
    	120 Weiss
    	121 Weiss1
    	122 Weiss2
    	123 Weiss3
    	124 Weiss4
    
    SQL>
    SQL> DECLARE
      v_last_name  VARCHAR2(25);
      v_emp_id     NUMBER(6) := 120;
    BEGIN
      <<get_name>>
      SELECT last_name INTO v_last_name
      FROM employees
      WHERE employee_id = v_emp_id;
      
      BEGIN
        DBMS_OUTPUT.PUT_LINE (v_last_name);
        v_emp_id := v_emp_id + 2;
     
        IF v_emp_id < 125 THEN
          GOTO get_name;
        END IF;
      END;
    END;
    /
      2    3    4    5    6    7    8    9   10   11   12   13   14   15   16   17   18   19  Weiss
    Weiss2
    Weiss4
    
    PL/SQL procedure successfully completed.
    
    SQL>
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45

    示例五:GOTO 语句将控制转移到 IF 语句,导致错误:

    SQL> DECLARE
      valid BOOLEAN := TRUE;
    BEGIN
      GOTO update_row;
      
      IF valid THEN
      <<update_row>>
        NULL;
      END IF;
    END;
    /
      2    3    4    5    6    7    8    9   10   11    GOTO update_row;
      *
    ERROR at line 4:
    ORA-06550: line 4, column 3:
    PLS-00375: illegal GOTO statement; this GOTO cannot branch to label 'UPDATE_ROW'
    ORA-06550: line 6, column 12:
    PL/SQL: Statement ignored
    
    
    SQL>
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21

    示例六:GOTO用在循环当中。作用类似于continue:

    SQL> create or replace procedure test111 is
      i integer;
    begin
      i := 2;
      loop
        <<next_step>>
        i := i * 2;
        if i > 100 then
          exit;
        end if; 
        if i > 50 then
          goto next_step;
        end if;
        dbms_output.put_line(i);
      end loop;
    end; 
    /
      2    3    4    5    6    7    8    9   10   11   12   13   14   15   16   17  
    Procedure created.
    
    SQL>
    SQL> call test111();
    4
    8
    16
    32
    
    Call completed.
    
    SQL>
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30

    如上:

    1. <>:这是循环标签,next_step是名字,可以自己定义
    2. goto next_step:表示i > 50后继续走到标签所在的位置执行代码
    3. 特别注意:<> 后面不能直接跟EXCEPTION、END LOOP这种关键字类的语句,可以用NULL把标签跟关键字隔开

    示例七:下面这个示例验证员工记录是否包含姓名、职位描述和员工雇用日期;如果缺少任何信息,则语句将执行点转移到打印一条消息的语句,该消息表明该员工无效:

    -- EDB数据库提供
    
    CREATE OR REPLACE PROCEDURE verify_emp (
        p_empno         NUMBER
    )
    IS
        v_ename         emp.ename%TYPE;
        v_job           emp.job%TYPE;
        v_hiredate      emp.hiredate%TYPE;
    BEGIN
        SELECT ename, job, hiredate
            INTO v_ename, v_job, v_hiredate FROM emp
            WHERE empno = p_empno;
        IF v_ename IS NULL THEN
            GOTO invalid_emp;
        END IF;
        IF v_job IS NULL THEN
            GOTO invalid_emp;
        END IF;
        IF v_hiredate IS NULL THEN
            GOTO invalid_emp;
        END IF;
        DBMS_OUTPUT.PUT_LINE('Employee ' || p_empno ||
            ' validated without errors.');
        RETURN;
        <<invalid_emp>> DBMS_OUTPUT.PUT_LINE('Employee ' || p_empno ||
            ' is not a valid employee.');
    END;
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28

    示例八:GOTO不能跳转到 exception 中:

    SQL> BEGIN
    	GOTO LB3; --expected error
    	EXCEPTION
    	WHEN OTHERS THEN
    	<<LB3>>
    	NULL;
    END;
    /
      2    3    4    5    6    7    8  	GOTO LB3; --expected error
    	*
    ERROR at line 2:
    ORA-06550: line 2, column 2:
    PLS-00375: illegal GOTO statement; this GOTO cannot branch to label 'LB3'
    ORA-06550: line 4, column 14:
    PL/SQL: Statement ignored
    
    
    SQL>
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18

    示例九:

    SQL> DECLARE
    	I INT := 0;
    BEGIN
    	<<LB1>>
    	I := I + 1;
    	dbms_output.put_line(I);
    	BEGIN
    		<<LB2>>
    		iF I = 1 THEN
    			RAISE INVALID_NUMBER;
    		ELSE
    			RAISE ZERO_DIVIDE;
    		END IF;
    		EXCEPTION
    		WHEN INVALID_NUMBER THEN
    		GOTO LB1; -- 如果跳转到 LB2 则报错,即:goto 语句不能从 EXCEPTION 中跳转到当前的语句块中
    		WHEN ZERO_DIVIDE THEN
    		dbms_output.put_line('ZERO_DIVIDE');
    	END;
    END;
    /
      2    3    4    5    6    7    8    9   10   11   12   13   14   15   16   17   18   19   20   21  1
    2
    ZERO_DIVIDE
    
    PL/SQL procedure successfully completed.
    
    SQL>
    SQL> DECLARE
    	I INT := 0;
    BEGIN
    	<<LB1>>
    	I := I + 1;
    	dbms_output.put_line(I);
    	BEGIN
    		<<LB2>>
    		iF I = 1 THEN
    			RAISE INVALID_NUMBER;
    		ELSE
    			RAISE ZERO_DIVIDE;
    		END IF;
    		EXCEPTION
    		WHEN INVALID_NUMBER THEN
    		GOTO LB2; -- 如果跳转到 LB2 则报错,即:goto 语句不能从 EXCEPTION 中跳转到当前的语句块中
    		WHEN ZERO_DIVIDE THEN
    		dbms_output.put_line('ZERO_DIVIDE');
    	END;
    END;
    /
    
      2    3    4    5    6    7    8    9   10   11   12   13   14   15   16   17   18   19   20   21  		GOTO LB2; -- 如果跳转到 LB2 则报错,即:goto 语句不能从 EXCEPTION 中跳转到当前的语句块中
    		*
    ERROR at line 16:
    ORA-06550: line 16, column 3:
    PLS-00375: illegal GOTO statement; this GOTO cannot branch to label 'LB2'
    ORA-06550: line 16, column 3:
    PL/SQL: Statement ignored
    
    
    SQL>
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56
    • 57
    • 58
    • 59
    • 60

    示例十:goto 到 goto标签

    SQL> BEGIN
      GOTO cmd1;
      DBMS_OUTPUT.PUT_LINE('i am cm  2    3  d.');
      <<cmd1>> DBMS_OUTPUT.PUT_LINE('i am cmd1.'  4  );
      GOTO cmd3;
      <<cmd2>> DBMS_OUTPUT.PUT_LINE('i  5    6   am cmd2.');
      <<cmd3>> GOTO cmd4;
      <<cmd4>> DBMS  7    8  _OUTPUT.PUT_LINE('i am cmd4.');
    END;
    /  9   10  
    i am cmd1.
    i am cmd4.
    
    PL/SQL procedure successfully completed.
    
    SQL>
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16

    当然这样的话,很容易就造成死循环,如下:

    -- 这种情况,只能手动停止
    
    SQL> BEGIN
      GOTO cmd1;
      DBMS_OUTPUT.PUT_LINE('i am cm  2    3  d.');
      <<cmd1>> DBMS_OUTPUT.PUT_LINE('i am cmd1.'  4  );
      GOTO cmd3;
      <<cmd2>> DBMS_OUTPUT.PUT_LINE('i  5    6   am cmd2.');
      <<cmd3>> GOTO cmd1; -- 又上去了,造成循环
      <<cmd4>> DBMS  7    8  _OUTPUT.PUT_LINE('i am cmd4.');
    END;
    /  9   10  
    ^CBEGIN
    *
    ERROR at line 1:
    ORA-01013: user requested cancel of current operation
    
    
    
    SQL>
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20

    示例十一:goto到相同标签

    SQL> BEGIN
      GOTO cmd1;
      <<cmd1>> DBMS_OUTPUT.PUT_LINE  2    3  ('i am cmd2.');
      <<cmd1>> DBMS_OUTPUT.PUT_LINE('i  4   am cmd4.');
    END;
    /  5    6  
      GOTO cmd1;
           *
    ERROR at line 2:
    ORA-06550: line 2, column 8:
    PLS-00371: at most one declaration for 'CMD1' is permitted
    ORA-06550: line 2, column 3:
    PL/SQL: Statement ignored
    
    
    SQL> BEGIN
      <<cmd1>> DBMS_OUTPUT.PUT_LINE('i am cmd2.'  2  );
      GOTO cmd1;
      <<cmd1>> DBMS_OUTPUT.PUT_LINE('i  3    4   am cmd4.');
    END;
    /  5    6  
      GOTO cmd1;
           *
    ERROR at line 3:
    ORA-06550: line 3, column 8:
    PLS-00371: at most one declaration for 'CMD1' is permitted
    ORA-06550: line 3, column 3:
    PL/SQL: Statement ignored
    
    
    SQL> BEGIN
      <<cmd1>> DBMS_OUTPUT.PUT_LINE('i am cmd2.'  2  );
      <<cmd1>> DBMS_OUTPUT.PUT_LINE('i am cmd4.');
      3    4    GOTO cmd1;
    END;
    /  5    6  
      GOTO cmd1;
           *
    ERROR at line 4:
    ORA-06550: line 4, column 8:
    PLS-00371: at most one declaration for 'CMD1' is permitted
    ORA-06550: line 4, column 3:
    PL/SQL: Statement ignored
    
    
    SQL>
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    BEGIN
      GOTO cmd1;
      <<cmd1>> DBMS_OUTPUT.PUT_LINE('i am cmd2.');
      <<cmd1>> DBMS_OUTPUT.PUT_LINE('i am cmd4.');
    END;
    /
    
    BEGIN
      <<cmd1>> DBMS_OUTPUT.PUT_LINE('i am cmd2.');
      GOTO cmd1;
      <<cmd1>> DBMS_OUTPUT.PUT_LINE('i am cmd4.');
    END;
    /
    
    BEGIN
      <<cmd1>> DBMS_OUTPUT.PUT_LINE('i am cmd2.');
      <<cmd1>> DBMS_OUTPUT.PUT_LINE('i am cmd4.');
      GOTO cmd1;
    END;
    /
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20

    NULL 语句的说明

    注意:如果启用了警告,使用NULL语句可能会引发不可达(unreachable code)代码警告。

    示例一:NULL表示没有动作的语句

    create table employees (employee_id number(6), last_name VARCHAR2(25));
    
    insert into employees values (120, 'Weiss');
    insert into employees values (121, 'Weiss1');
    insert into employees values (122, 'Weiss2');
    insert into employees values (123, 'Weiss3');
    insert into employees values (124, 'Weiss4');
    
    DECLARE
       v_last_name  VARCHAR2(10);
       v_emp_id     NUMBER(6) := 123;
    BEGIN
      SELECT last_name INTO v_last_name FROM employees WHERE employee_id = v_emp_id;
      
      IF v_last_name = 'Weiss3' THEN
        UPDATE employees SET last_name = 'Weiss321';
      ELSE
        NULL;  -- Employee is not a sales rep
      END IF;
    END;
    /
    
    select * from employees;
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23

    在这里插入图片描述


    示例二:在子程序创建期间作为占位符的NULL语句

    -- NULL语句允许您编译这个子程序,并在以后填充真正的主体
    
    CREATE OR REPLACE PROCEDURE award_bonus (
      emp_id NUMBER,
      bonus NUMBER
    ) AUTHID DEFINER AS
    BEGIN    -- Executable part starts here
      NULL;  -- Placeholder
      -- (raises "unreachable code" if warnings enabled)
    END award_bonus;
    /
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11

    在这里插入图片描述


    示例三:简单CASE语句ELSE子句中的NULL语句

    CREATE OR REPLACE PROCEDURE print_grade (
      grade CHAR
    ) AUTHID DEFINER AS
    BEGIN
      CASE grade
        WHEN 'A' THEN DBMS_OUTPUT.PUT_LINE('Excellent');
        WHEN 'B' THEN DBMS_OUTPUT.PUT_LINE('Very Good');
        WHEN 'C' THEN DBMS_OUTPUT.PUT_LINE('Good');
        WHEN 'D' THEN DBMS_OUTPUT.PUT_LINE('Fair');
        WHEN 'F' THEN DBMS_OUTPUT.PUT_LINE('Poor');
        ELSE NULL;
      END CASE;
    END;
    /
    BEGIN
      print_grade('A');
      print_grade('S');
    END;
    /
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19

    在这里插入图片描述

  • 相关阅读:
    【LeetCode每日一题】——72.编辑距离
    “灯塔工厂”的中国路径:智造从点到面铺开
    软件测试突破技术瓶颈之python接口自动化- DDT数据驱动测试
    java计算机毕业设计springboot+vue基本微信的医院网站小程序 uniapp
    全排列——dfs(剪枝/回溯)
    【LeetCode第115场双周赛】100029. 和带限制的子多重集合的数目 | 前缀和背包 | 中等
    C#字符串操作:拼接、截取、分割等高效处理方法
    iptables
    【收藏】网络设备安全加固规范
    idea 无法识别maven的解决
  • 原文地址:https://blog.csdn.net/weixin_43949535/article/details/128110250