第四章  控制结构(也比较基础,就只做例子了)

--MEMBER OF的使用
23:14:07 SCOTT@orcl> DECLARE
23:14:09   2    TYPE LIST IS TABLE OF VARCHAR2(10);
23:14:09   3    N VARCHAR2(10) := 'One';
23:14:09   4    A LIST := LIST('One', 'Two', 'Three');
23:14:09   5  BEGIN
23:14:09   6    IF N MEMBER OF A THEN
23:14:09   7      DBMS_OUTPUT.PUT_LINE('"n" is member.');
23:14:09   8    END IF;
23:14:09   9  END;
23:14:11  10  /
"n" is member.PL/SQL 过程已成功完成。
--SUBMULTISET的使用
23:14:13 SCOTT@orcl> DECLARE
23:15:33   2    TYPE LIST IS TABLE OF INTEGER;
23:15:33   3    A LIST := LIST(1, 2, 3);
23:15:33   4    B LIST := LIST(1, 2, 3, 4);
23:15:33   5  BEGIN
23:15:33   6    IF A SUBMULTISET B THEN
23:15:33   7      DBMS_OUTPUT.PUT_LINE('Subset.');
23:15:33   8    END IF;
23:15:33   9  END;
23:15:34  10  /
Subset.PL/SQL 过程已成功完成。

1.IF语句
格式:
IF [NOT] {comparison_expression | boolean_value} [[AND | OR]
         {comparison_expression | boolean_value}] THEN
         true_execution_block;
  [ELSE
         false_execution_block;]
END IF;

23:19:29 SCOTT@orcl> DECLARE
23:19:35   2    ONE_THING VARCHAR2(5) := 'Three';
23:19:35   3    FUNCTION ORDINAL(N NUMBER) RETURN VARCHAR2 IS
23:19:35   4      TYPE ORDINAL_TYPE IS TABLE OF VARCHAR2(5);
23:19:35   5      ORDINAL ORDINAL_TYPE := ORDINAL_TYPE('One', 'Two', 'Three', 'our');
23:19:35   6    BEGIN
23:19:35   7      RETURN ORDINAL(N);
23:19:35   8    END;
23:19:35   9  BEGIN
23:19:35  10    IF ONE_THING = ORDINAL(3) THEN
23:19:35  11      DBMS_OUTPUT.PUT_LINE('[' || ORDINAL(3) || ']');
23:19:35  12    END IF;
23:19:35  13  END;
23:19:36  14  /
[Three]PL/SQL 过程已成功完成。

2.CASE语句
CASE [ TRUE | [selector_variable]]
  WHEN [criterion1 | expression1] THEN
   criterion1_statements;
  WHEN [criterion2 | expression2] THEN
   criterion2_statements;
  WHEN [criterion(n+1) | expression(n+1)] THEN
   criterion(n+1)_statements;
ELSE
   block_statements;
END CASE;

3.迭代语句

23:24:02 SCOTT@orcl> DECLARE
23:24:04   2    COUNTER NUMBER;
23:24:04   3    FIRST   BOOLEAN;
23:24:04   4  BEGIN
23:24:04   5    LOOP
23:24:04   6      -- Loop index management.
23:24:04   7      IF NVL(COUNTER, 1) >= 1 THEN
23:24:04   8        IF NOT NVL(FIRST, TRUE) THEN
23:24:04   9          COUNTER := COUNTER + 1;
23:24:04  10        ELSE
23:24:04  11          COUNTER := 1;
23:24:04  12          FIRST   := FALSE;
23:24:04  13        END IF;
23:24:04  14      END IF;
23:24:04  15      -- Exit management.
23:24:04  16      EXIT WHEN NOT COUNTER < 3;
23:24:04  17      DBMS_OUTPUT.PUT_LINE('Iteration [' || COUNTER || ']');
23:24:04  18    END LOOP;
23:24:04  19  END;
23:24:04  20  /
Iteration [1]
Iteration [2]PL/SQL 过程已成功完成。
23:24:05 hr@orcl> DECLARE
23:26:06   2    COUNTER NUMBER;
23:26:06   3    FIRST   BOOLEAN;
23:26:06   4  BEGIN
23:26:06   5    LOOP
23:26:06   6      -- Loop index management.
23:26:06   7      IF NVL(COUNTER, 1) >= 1 THEN
23:26:06   8        IF NOT NVL(FIRST, TRUE) THEN
23:26:06   9          COUNTER := COUNTER + 1;
23:26:06  10        ELSE
23:26:06  11          COUNTER := 1;
23:26:06  12          FIRST   := FALSE;
23:26:06  13        END IF;
23:26:06  14      END IF;
23:26:06  15      DBMS_OUTPUT.PUT_LINE('Iteration [' || COUNTER || ']');
23:26:06  16      -- Exit management.
23:26:06  17      EXIT WHEN NOT COUNTER < 3;
23:26:06  18    END LOOP;
23:26:06  19  END;
23:26:07  20  /
Iteration [1]
Iteration [2]
Iteration [3]PL/SQL 过程已成功完成。
--CONTINUE的使用
23:35:55 hr@orcl> DECLARE
23:35:57   2    COUNTER NUMBER;
23:35:57   3    FIRST   BOOLEAN;
23:35:57   4  BEGIN
23:35:57   5    LOOP
23:35:57   6      -- Loop index management.
23:35:57   7      IF NVL(COUNTER, 1) >= 1 THEN
23:35:57   8        IF NOT NVL(FIRST, TRUE) THEN
23:35:57   9          COUNTER := COUNTER + 1;
23:35:57  10        ELSE
23:35:57  11          COUNTER := 1;
23:35:57  12          FIRST   := FALSE;
23:35:57  13        END IF;
23:35:57  14      END IF;
23:35:57  15      -- Exit management.
23:35:57  16      EXIT WHEN NOT COUNTER < 3;
23:35:57  17      IF COUNTER = 2 THEN
23:35:57  18        CONTINUE;
23:35:57  19      ELSE
23:35:57  20        DBMS_OUTPUT.PUT_LINE('Index [' || COUNTER || '].');
23:35:57  21      END IF;
23:35:57  22    END LOOP;
23:35:57  23  END;
23:35:57  24  /
Index [1].PL/SQL 过程已成功完成。

4.FOR循环语句
格式:
FOR range_index IN range_bottom..range_top LOOP
  repeating_statements;
END LOOP;

23:35:59 hr@orcl> BEGIN
23:38:44   2  FOR i IN 1..3 LOOP
23:38:44   3  dbms_output.put_line('Iteration ['||i||']');
23:38:44   4  END LOOP;
23:38:44   5  END;
23:38:46   6  /
Iteration [1]
Iteration [2]
Iteration [3]PL/SQL 过程已成功完成。

--游标FOR循环
BEGIN
  FOR I IN (SELECT COUNT(*) AS ON_HAND, ITEM_TITLE, ITEM_RATING
              FROM ITEM
             WHERE ITEM_TITLE LIKE 'Harry Potter%'
               AND ITEM_RATING_AGENCY = 'MPAA'
             GROUP BY ITEM_TITLE, ITEM_RATING) LOOP
    DBMS_OUTPUT.PUT('(' || I.ON_HAND || ') ');
    DBMS_OUTPUT.PUT(I.ITEM_TITLE || ' ');
    DBMS_OUTPUT.PUT_LINE('[' || I.ITEM_RATING || ']');
  END LOOP;
END;

5.WHILE循环语句
格式:
WHILE entry_condition LOOP
  [counter_management_statements;]
  repeating_statements;
END LOOP;
例:

23:38:47 hr@orcl> DECLARE
23:40:35   2    COUNTER NUMBER := 1;
23:40:35   3  BEGIN
23:40:35   4    WHILE (COUNTER < 3) LOOP
23:40:35   5      DBMS_OUTPUT.PUT_LINE('Index [' || COUNTER || '].');
23:40:35   6      IF COUNTER >= 1 THEN
23:40:35   7        COUNTER := COUNTER + 1;
23:40:35   8      END IF;
23:40:35   9    END LOOP;
23:40:35  10  END;
23:40:35  11  /
Index [1].
Index [2].PL/SQL 过程已成功完成。
--goto的使用
23:40:36 hr@orcl> DECLARE
23:41:34   2    COUNTER NUMBER := 1;
23:41:34   3  BEGIN
23:41:34   4    WHILE (COUNTER < 3) LOOP
23:41:34   5      IF COUNTER = 2 THEN
23:41:34   6        GOTO LOOPINDEX;
23:41:34   7      ELSE
23:41:34   8        DBMS_OUTPUT.PUT_LINE('Index [' || COUNTER || '].');
23:41:34   9      END IF;
23:41:34  10      <<LOOPINDEX>>
23:41:34  11      IF COUNTER >= 1 THEN
23:41:34  12        COUNTER := COUNTER + 1;
23:41:34  13      END IF;
23:41:34  14    END LOOP;
23:41:34  15  END;
23:41:35  16  /
Index [1].PL/SQL 过程已成功完成。

6.游标结构
  隐式游标

--隐式游标的%ROWCOUN属性
23:41:35 hr@orcl> DECLARE
23:43:06   2    N NUMBER;
23:43:06   3  BEGIN
23:43:06   4    SELECT 1 INTO N FROM DUAL;--单行隐式游标
23:43:06   5    DBMS_OUTPUT.PUT_LINE('Selected [' || SQL%ROWCOUNT || ']');
23:43:06   6  END;
23:43:06   7  /
Selected [1]PL/SQL 过程已成功完成。

--记录类型的使用
DECLARE
  TYPE ITEM_RECORD IS RECORD(
    ID       ITEM.ITEM_ID%TYPE,
    TITLE    ITEM.ITEM_TITLE%TYPE,
    SUBTITLE ITEM.ITEM_SUBTITLE%TYPE);
  DATASET ITEM_RECORD;
BEGIN
  SELECT ITEM_ID, ITEM_TITLE, ITEM_SUBTITLE
    INTO DATASET
    FROM ITEM
   WHERE ROWNUM < 2;
  DBMS_OUTPUT.PUT_LINE('Selected [' || DATASET.TITLE || ']');
END;

--多行隐式游标
BEGIN
  UPDATE SYSTEM_USER SET LAST_UPDATE_DATE = SYSDATE;
  IF SQL%FOUND THEN
    DBMS_OUTPUT.PUT_LINE('Updated [' || SQL%ROWCOUNT || ']');
  ELSE
    DBMS_OUTPUT.PUT_LINE('Nothing updated!');
  END IF;
END;

--多行隐式游标
BEGIN
  FOR I IN (SELECT ITEM_ID, ITEM_TITLE FROM ITEM) LOOP--这种隐式游标的SQL%ROWCOUNT属性将返回NULL
    DBMS_OUTPUT.PUT_LINE('Item #[' || I.ITEM_ID || '][' || I.ITEM_TITLE || ']');
  END LOOP;
END;
  
  显示游标
静态显示游标
DECLARE
  ID    ITEM.ITEM_ID%TYPE;
  TITLE VARCHAR2(60);
  CURSOR C IS
    SELECT ITEM_ID, ITEM_TITLE FROM ITEM;
BEGIN
  OPEN C;
  LOOP
    FETCH C
      INTO ID, TITLE;
    EXIT WHEN C%NOTFOUND;
    DBMS_OUTPUT.PUT_LINE('Title [' || TITLE || ']');
  END LOOP;
  CLOSE C;
END;
等价于=>
DECLARE
  CURSOR C IS
    SELECT ITEM_ID AS ID, ITEM_TITLE AS TITLE FROM ITEM;
BEGIN
  FOR I IN C LOOP
    DBMS_OUTPUT.PUT_LINE('Title [' || I.TITLE || ']');
  END LOOP;
END;

--显示游标中使用记录类型
DECLARE
  TYPE ITEM_RECORD IS RECORD(
    ID    NUMBER,
    TITLE VARCHAR2(60));
  ITEM ITEM_RECORD;
  CURSOR C IS
    SELECT ITEM_ID, ITEM_TITLE FROM ITEM;
BEGIN
  OPEN C;
  LOOP
    FETCH C
      INTO ITEM;
    EXIT WHEN C%NOTFOUND;
    DBMS_OUTPUT.PUT_LINE('Title [' || ITEM.TITLE || ']');
  END LOOP;
END;
等价于=>
DECLARE
  TYPE ITEM_RECORD IS RECORD(
    ID    NUMBER,
    TITLE VARCHAR2(60));
  EXPLICIT_ITEM ITEM_RECORD;
  CURSOR C IS
    SELECT ITEM_ID AS ID, ITEM_TITLE AS TITLE FROM ITEM;
BEGIN
  FOR I IN C LOOP
    EXPLICIT_ITEM := I;
    DBMS_OUTPUT.PUT_LINE('Title [' || EXPLICIT_ITEM.TITLE || ']');
  END LOOP;
END;

--有条件的退出循环,这种显示游标无法用FOR循环改写
DECLARE
  TYPE ITEM_RECORD IS RECORD(
    ID    NUMBER,
    TITLE VARCHAR2(60));
  ITEM ITEM_RECORD;
  CURSOR C IS
    SELECT ITEM_ID, ITEM_TITLE FROM ITEM WHERE ITEM_ID = -1;
BEGIN
  OPEN C;
  LOOP
    FETCH C
      INTO ITEM;
    IF C%NOTFOUND THEN
      IF C%ROWCOUNT = 0 THEN
        DBMS_OUTPUT.PUT_LINE('No Data Found');
      END IF;
      EXIT;
    ELSE
      DBMS_OUTPUT.PUT_LINE('Title [' || ITEM.TITLE || ']');
    END IF;
  END LOOP;
END;
 
动态显示游标
DECLARE
  LOWEND  NUMBER;
  HIGHEND NUMBER;
  ITEM_ID NUMBER := 1012;
  TYPE ITEM_RECORD IS RECORD(
    ID    NUMBER,
    TITLE VARCHAR2(60));
  ITEM ITEM_RECORD;
  CURSOR C(LOW_ID NUMBER, HIGH_ID NUMBER) IS--带参游标
    SELECT ITEM_ID, ITEM_TITLE
      FROM ITEM
     WHERE ITEM_ID BETWEEN LOW_ID AND HIGH_ID;
BEGIN
  LOWEND  := TO_NUMBER(NVL(&1, 1005));
  HIGHEND := TO_NUMBER(NVL(&2, 1021));
  OPEN C(LOWEND, HIGHEND);
  LOOP
    FETCH C
      INTO ITEM;
    EXIT WHEN C%NOTFOUND;
    DBMS_OUTPUT.PUT_LINE('Title [' || ITEM.TITLE || ']');
  END LOOP;
END;
使用部分改写为FOR循环为:
FOR i IN c (lowend,highend) LOOP
item := i;
dbms_output.put_line('Title ['||item.title||']');
END LOOP;

7.BULK语句
BULK语句让你从表或视图查询、插入、更新、删除大数据集.
它有2个游标属性:
  %BULK_ROWCOUNT(I):查看元素是否被更改
  %BULK_EXCEPTION(I):查看某行是否遇到错误
格式:
SELECT column1 [, column2 [, column(n+1)]]
       COLLECT BULK INTO collection1 [, collection2 [, collection(n+1)]]
FROM table_name
[WHERE where_clause_statements];

FETCH cursor_name [(parameter1 [, parameter2 [, parameter(n+1)]])]
  BULK COLLECT INTO collection1 [, collection2 [, collection(n+1)]]
[LIMIT rows_to_return];
--隐式BULK游标,SELECT BULK是并行执行的
DECLARE
  TYPE TITLE_COLLECTION IS TABLE OF VARCHAR2(60);
  TYPE SUBTITLE_COLLECTION IS TABLE OF VARCHAR2(60);
  TITLE    TITLE_COLLECTION;
  SUBTITLE SUBTITLE_COLLECTION;
BEGIN
  SELECT ITEM_TITLE, ITEM_SUBTITLE BULK COLLECT
    INTO TITLE, SUBTITLE
    FROM ITEM;
  -- Print one element of one of the parallel collections.
  FOR I IN 1 .. TITLE.COUNT LOOP
    DBMS_OUTPUT.PUT_LINE('Title [' || TITLE(I) || ']');
  END LOOP;
END;

--BULK中使用记录变量
DECLARE
  TYPE TITLE_RECORD IS RECORD(
    TITLE    VARCHAR2(60),
    SUBTITLE VARCHAR2(60));
  TYPE COLLECTION IS TABLE OF TITLE_RECORD;
  FULL_TITLE COLLECTION;
BEGIN
  SELECT ITEM_TITLE, ITEM_SUBTITLE BULK COLLECT INTO FULL_TITLE FROM ITEM;
  -- Print one element of a structure.
  FOR I IN 1 .. FULL_TITLE.COUNT LOOP
    DBMS_OUTPUT.PUT_LINE('Title [' || FULL_TITLE(I).TITLE || ']');
  END LOOP;
END;

--并行行数限制
DECLARE
  -- Define scalar datatypes.
  TYPE TITLE_COLLECTION IS TABLE OF VARCHAR2(60);
  TYPE SUBTITLE_COLLECTION IS TABLE OF VARCHAR2(60);
  -- Define local variables.
  TITLE    TITLE_COLLECTION;
  SUBTITLE SUBTITLE_COLLECTION;
  -- Define a static cursor.
  CURSOR C IS
    SELECT ITEM_TITLE, ITEM_SUBTITLE FROM ITEM;
BEGIN
  OPEN C;
  LOOP
    FETCH C BULK COLLECT
      INTO TITLE, SUBTITLE LIMIT 10;--限制每10个一次
    EXIT WHEN TITLE.COUNT = 0;
    FOR I IN 1 .. TITLE.COUNT LOOP
      DBMS_OUTPUT.PUT_LINE('Title [' || TITLE(I) || ']');
    END LOOP;
  END LOOP;
END;

8. FORALL语句
FORALL语句设计用来处理集合类型的.
--使用FORALL进行批量插入
DECLARE
  TYPE ID_COLLECTION IS TABLE OF NUMBER;
  TYPE TITLE_COLLECTION IS TABLE OF VARCHAR2(60);
  TYPE SUBTITLE_COLLECTION IS TABLE OF VARCHAR2(60);
  ID       ID_COLLECTION;
  TITLE    TITLE_COLLECTION;
  SUBTITLE SUBTITLE_COLLECTION;
  CURSOR C IS
    SELECT ITEM_ID, ITEM_TITLE, ITEM_SUBTITLE FROM ITEM;
BEGIN
  OPEN C;
  LOOP
    FETCH C BULK COLLECT
      INTO ID, TITLE, SUBTITLE LIMIT 10;
    EXIT WHEN TITLE.COUNT = 0;
    FORALL I IN ID.FIRST .. ID.LAST --FORALL的使用
      INSERT INTO ITEM_TEMP VALUES (ID(I), TITLE(I), SUBTITLE(I));
  END LOOP;
  FOR I IN ID.FIRST .. ID.LAST LOOP
    DBMS_OUTPUT.PUT('Inserted [' || ID(I) || ']');
    DBMS_OUTPUT.PUT_LINE('[' || SQL%BULK_ROWCOUNT(I) || ']');
  END LOOP;
END;

--使用FORALL进行批量更新
DECLARE
  TYPE ID_COLLECTION IS TABLE OF NUMBER;
  TYPE TITLE_COLLECTION IS TABLE OF VARCHAR2(60);
  ID    ID_COLLECTION;
  TITLE TITLE_COLLECTION;
  CURSOR C IS
    SELECT ITEM_ID, ITEM_TITLE FROM ITEM;
BEGIN
  OPEN C;
  LOOP
    FETCH C BULK COLLECT
      INTO ID, TITLE LIMIT 10;
    EXIT WHEN TITLE.COUNT = 0;
    FORALL I IN ID.FIRST .. ID.LAST
      UPDATE ITEM_TEMP SET TITLE = TITLE(I) || ': ' WHERE ID = ID(I);
  END LOOP;
END;

--使用FORALL进行批量删除
DECLARE
  TYPE ID_COLLECTION IS TABLE OF NUMBER;
  TYPE TITLE_COLLECTION IS TABLE OF VARCHAR2(60);
  ID    ID_COLLECTION;
  TITLE TITLE_COLLECTION;
  CURSOR C IS
    SELECT ITEM_ID, ITEM_TITLE FROM ITEM;
BEGIN
  OPEN C;
  LOOP
    FETCH C BULK COLLECT
      INTO ID, TITLE LIMIT 10;
    EXIT WHEN TITLE.COUNT = 0;
    FORALL I IN ID.FIRST .. ID.LAST
      DELETE FROM ITEM_TEMP
       WHERE SUBTITLE IS NULL
         AND ID = ID(I);
  END LOOP;

END;

第5章 错误管理(Error Management)

异常类型和异常处理范围
有两种类型的错误:编译错误和运行时错误.编译错误在语法解析的时候就会发现,运行时错误是当实际数据在程序中按
预定规则处理的时候发生的错误.
运行时错误一般都会在当前块被异常处理捕捉到(声明块的异常无法被当前异常处理块捕捉),编译错误(如声明处变量定义错误)当前块无法捕捉.
编译错误
编译错误很常见,如果你输错关键字,忘记分号,忘记括号等等,都会引发编译错误.
如:

--少分号的
22:11:57 hr@orcl> BEGIN
22:12:19   2   dbms_output.put_line('Hello World.')
22:12:19   3  END;
22:12:21   4  /
END;
*
第 3 行出现错误:
ORA-06550: 第 3 行, 第 1 列:
PLS-00103: 出现符号 "END"在需要下列之一时:
:= . ( % ;
符号 ";" 被替换为 "END" 后继续。
--未定义类型长度
22:12:22 hr@orcl> DECLARE
22:13:51   2    A CHAR := 'AB';--未定义类型长度
22:13:51   3  BEGIN
22:13:51   4    DBMS_OUTPUT.PUT_LINE('[' || A || ']');
22:13:51   5  END;
22:13:52   6  /
DECLARE
*
第 1 行出现错误:
ORA-06502: PL/SQL: 数字或值错误 :  字符串缓冲区太小
ORA-06512: 在 line 2

综上可以看出编译错误,给出的错误提示一般是不准确的,需要自己去判断.

运行时错误
运行时错误可以发生在声明块、执行块、异常块.声明块及异常块发生的运行时错误只有外部异常块才能捕捉.
异常块格式:
WHEN {predefined_exception | user_defined_exception | OTHERS} THEN
     exception_handling_statement;
[RETURN | EXIT ];
异常块处理的异常分为系统预定义异常、用户自定义异常及其他异常.
系统预定义异常定义在SYS.STANDARD包里,异常块里常用SQLCODE和SQLERRM两个函数输出错误信息.

系统预定义异常对照表

SQLCODE输出一个oracle预定义的负数,此负数对应oracle系统一系列预定义异常.
注意:有一个异常是例外的NO_DATA_FOUND异常返回的SQLCODE是100.
SQLERRM返回错误信息及定义的错误代码.
例:

--系统预定义异常VALUE_ERROR
22:25:51 hr@orcl> DECLARE
22:25:59   2    A VARCHAR2(1);
22:25:59   3    B VARCHAR2(2) := 'AB';
22:25:59   4  BEGIN
22:25:59   5    A := B;--这里发生运行时错误
22:25:59   6  EXCEPTION
22:25:59   7    WHEN VALUE_ERROR THEN
22:25:59   8      DBMS_OUTPUT.PUT_LINE('You can''t put [' || B ||'] in a one character string.');
22:25:59  10  END;
22:25:59  11  /
You can't put [AB] in a one character string.PL/SQL 过程已成功完成。--用WHEN OHTERS捕捉系统预定义异常NO_DATA_FOUND
22:26:00 hr@orcl> DECLARE
22:28:44   2    A NUMBER;
22:28:44   3  BEGIN
22:28:44   4    DECLARE
22:28:44   5      B VARCHAR2(2);
22:28:44   6    BEGIN
22:28:44   7      SELECT 1 INTO B FROM DUAL WHERE 1 = 2;--此处发生运行时错误
22:28:44   8      A := B;
22:28:44   9    EXCEPTION--里层异常处理
22:28:44  10      WHEN VALUE_ERROR THEN
22:28:44  11        DBMS_OUTPUT.PUT_LINE('You can''t put [' || B ||
22:28:44  12                             '] in a one character string.');
22:28:44  13    END;
22:28:44  14  EXCEPTION--外层异常处理
22:28:44  15    WHEN OTHERS THEN
22:28:44  16      DBMS_OUTPUT.PUT_LINE('Caught in outer block [' || SQLERRM || '].');
22:28:44  17  END;
22:28:46  18  /
Caught in outer block [ORA-01403: 未找到任何数据].PL/SQL 过程已成功完成。
--用户自定义异常
22:28:47 hr@orcl> DECLARE
22:31:24   2    A NUMBER;
22:31:24   3    E EXCEPTION;
22:31:24   4  BEGIN
22:31:24   5    DECLARE
22:31:24   6      B VARCHAR2(2) := 'AB';
22:31:24   7    BEGIN
22:31:24   8      RAISE E;--主动抛出异常,注意此异常变量是在外层定义的,所以只能被外层捕捉
22:31:24   9    EXCEPTION
22:31:24  10      WHEN OTHERS THEN
22:31:24  11        A := B;
22:31:24  12        DBMS_OUTPUT.PUT_LINE('Does not reach this line.');
22:31:24  13    END;
22:31:24  14  EXCEPTION
22:31:24  15    WHEN OTHERS THEN --此处捕捉异常
22:31:24  16      DBMS_OUTPUT.PUT_LINE('Caught in outer block [' || SQLCODE || '].');
22:31:24  17  END;
22:31:25  18  /
Caught in outer block [-6502].PL/SQL 过程已成功完成。
--声明处的运行时错误,当前的异常块是无法捕捉当前声明块的运行时错误的
22:34:33 hr@orcl> DECLARE
22:34:35   2    A VARCHAR2(1) := 'a1';
22:34:35   3  BEGIN
22:34:35   4    DBMS_OUTPUT.PUT_LINE('Substituted variable value [' || A || ']');
22:34:35   5  EXCEPTION
22:34:35   6    WHEN OTHERS THEN
22:34:35   7      DBMS_OUTPUT.PUT_LINE('Local exception caught.');
22:34:35   8  END;
22:34:35   9  /
DECLARE
*
第 1 行出现错误:
ORA-06502: PL/SQL: 数字或值错误 :  字符串缓冲区太小
ORA-06512: 在 line 2
--外部异常块捕捉声明处运行时错误
22:36:42 hr@orcl> BEGIN
22:37:21   2    DECLARE
22:37:21   3      A VARCHAR2(1) := 'a1';--内部声明块发生运行时错误
22:37:21   4    BEGIN
22:37:21   5      DBMS_OUTPUT.PUT_LINE('Substituted variable value [' || A || ']');
22:37:21   6    EXCEPTION
22:37:21   7      WHEN OTHERS THEN
22:37:21   8        DBMS_OUTPUT.PUT_LINE('Local exception caught.');
22:37:21   9    END;
22:37:21  10  EXCEPTION
22:37:21  11    WHEN OTHERS THEN--外部异常块捕捉到
22:37:21  12      DBMS_OUTPUT.PUT_LINE('Outer exception caught.');
22:37:21  13  END;
22:37:21  14  /
Outer exception caught.PL/SQL 过程已成功完成。
--函数中的声明块异常处理
--注:不建议在声明处使用动态赋值
22:41:39 hr@orcl> CREATE OR REPLACE FUNCTION RUNTIME_ERROR(VARIABLE_IN VARCHAR2)
22:41:43   2    RETURN VARCHAR2 IS
22:41:43   3    A VARCHAR2(1) := VARIABLE_IN;
22:41:43   4  BEGIN
22:41:43   5    RETURN NULL;
22:41:43   6  EXCEPTION
22:41:43   7    WHEN OTHERS THEN
22:41:43   8      DBMS_OUTPUT.PUT_LINE('Function error.');
22:41:43   9  END;
22:41:44  10  /函数已创建。
--发生声明处错误,异常处理块未捕捉到
22:41:45 hr@orcl> SELECT runtime_error ('AB') FROM dual;
SELECT runtime_error ('AB') FROM dual*
第 1 行出现错误:
ORA-06502: PL/SQL: 数字或值错误 :  字符串缓冲区太小
ORA-06512: 在 "GW.RUNTIME_ERROR", line 3

用户自定义异常
两种类型的用户自定义异常:
1.在声明处声明EXCEPTION类型的变量;
2.使用函数RAISE_APPLICATION_ERROR在执行块动态建立异常(使用的异常号范围为-20000到-20999)
例:

--第一类用户自定义异常
22:57:37 hr@orcl> DECLARE
22:57:41   2    E EXCEPTION;
22:57:41   3  BEGIN
22:57:41   4    RAISE E;
22:57:41   5    DBMS_OUTPUT.PUT_LINE('Can''t get here.');
22:57:41   6  EXCEPTION
22:57:41   7    WHEN OTHERS THEN
22:57:41   8      IF SQLCODE = 1 THEN--所有用户自定义异常的SQLCODE都为1
22:57:41   9        DBMS_OUTPUT.PUT_LINE('This is a [' || SQLERRM || '].');
22:57:41  10      END IF;
22:57:41  11  END;
22:57:41  12  /
This is a [User-Defined Exception].PL/SQL 过程已成功完成。
--第一类用户自定义异常,绑定了系统的预定义错误号-2003
22:57:42 hr@orcl> DECLARE
22:59:54   2    A VARCHAR2(20);
22:59:54   3    INVALID_USERENV_PARAMETER EXCEPTION;
22:59:54   4    PRAGMA EXCEPTION_INIT(INVALID_USERENV_PARAMETER, -2003);
22:59:54   5  BEGIN
22:59:54   6    A := SYS_CONTEXT('USERENV', 'PROXY_PUSHER');
22:59:54   7  EXCEPTION
22:59:54   8    WHEN INVALID_USERENV_PARAMETER THEN
22:59:54   9      DBMS_OUTPUT.PUT_LINE(SQLERRM);
22:59:54  10  END;
22:59:55  11  /
ORA-02003: 无效的 USERENV 参数PL/SQL 过程已成功完成。--第二类用户自定义异常
22:59:56 hr@orcl> BEGIN
23:01:34   2    RAISE_APPLICATION_ERROR(-20001, 'A not too original message.');
23:01:34   3  EXCEPTION
23:01:34   4    WHEN OTHERS THEN
23:01:34   5      DBMS_OUTPUT.PUT_LINE(SQLERRM);
23:01:34   6  END;
23:01:35   7  /
ORA-20001: A not too original message.PL/SQL 过程已成功完成。--一、二类用户自定义异常结合使用
23:01:35 hr@orcl> DECLARE
23:03:20   2    E EXCEPTION;--定义异常变量
23:03:20   3    PRAGMA EXCEPTION_INIT(E, -20001);--绑定错误号-20001
23:03:20   4  BEGIN
23:03:20   5    RAISE_APPLICATION_ERROR(-20001, 'A less than original message.');--抛出异常
23:03:20   6  EXCEPTION
23:03:20   7    WHEN E THEN--捕捉异常,-20001和E已经绑定
23:03:20   8      DBMS_OUTPUT.PUT_LINE(SQLERRM);
23:03:20   9  END;
23:03:20  10  /
ORA-20001: A less than original message.PL/SQL 过程已成功完成。

转载于:https://www.cnblogs.com/xinyuyuanm/archive/2013/04/18/3028437.html

oracle 11g PL/SQL Programming学习三相关推荐

  1. 判断题:oracle自带的sql语言环境是pl/sql,Oracle之PL/SQL学习笔记之数据类型(三)

    Oracle之PL/SQL学习笔记之数据类型(三) 所有的编程语言中变量是使用最频繁的.PL/SQL作为一个面向过程的数据库编程语言同样少不了变量,利用变量可以把PL/SQL块需要的参数传递进来,做到 ...

  2. Oracle之PL/SQL学习笔记之有名块练习

    2019独角兽企业重金招聘Python工程师标准>>> Oracle之PL/SQL学习笔记之有名块练习 存储过程案例: 案例1: 根据雇员姓名跟新雇员工资,如果雇员不存在输出没有该雇 ...

  3. oracle实战编程,Oracle Databa se 11g PL/SQL编程实战_IT教程网

    资源名称:Oracle Database 11g PL/SQL编程实战 内容简介: <oracle database 11gpl/sql编程实战>通过动手练习.大量的示例以及实际的项目帮助 ...

  4. 从永远到永远-Oracle的PL/SQL学习(存储过程学习)

    工作原因,涉及到了Oracle数据库的存储过程.以前没有接触过,请教了很多大佬,被喷的.被误导.被折腾的半4.总算是领悟了一点点的东西,现有时间总结下自己的一些感触. 1.关于PL/SQL 1.1 是 ...

  5. Oracle之PL/SQL编程从入门到精通-文心-专题视频课程

    Oracle之PL/SQL编程从入门到精通-23941人已学习 课程介绍         本课程基于Oracle数据库,讲解PL/SQLl编程方面的技能,通过本课程的学习,学员能在短的时间内掌握Ora ...

  6. Oracle的PL/SQL编程前奏之基础技能实战一(匿名子程序)

    Oracle的PL/SQL编程之基础技能实战一 一>基础代码检查检查以bm_开头的系统初始化编码表是否有空值.与业务系统相关的编码项不能存在空值,会导致系统业务无法办理.为初始化数据表.在做测试 ...

  7. oracle 12c sql图形化,Oracle 12c PL/SQL程序设计终极指南

    Oracle 12c PL/SQL程序设计终极指南 作者:孙风栋;王澜;郭晓惠 出版日期:2015年06月 文件大小:11.73M 支持设备: ¥60.00在线试读 适用客户端: 言商书局 iPad/ ...

  8. Oracle(五)PL/SQL编程语言

    Oracle(五)PL/SQL编程语言 ---pl/sql编程语言 ---pl/sql语言是对sql语言的扩展,使得sql语言具有过程化编程的特性. ---pl/sql编程语言比一般的过程化编程语言, ...

  9. Oracle数据库PL/SQL块-存储函数和过程

    PL/SQL块 PL/SQL程序由三个块组成,即声明部分.执行部分.异常处理部分 结构如下: declare​ /*声明部分,在此声明变量,类型及游标*/begin​ /*执行部分,过程及sql语句, ...

  10. PL/SQL 入门学习(一)

    前言:本博客分为两篇,学完之后就可以在项目中使用存储过程进行开发. 在学校的时候虽说上过PL/SQL这门课,然并卵,只恨当时啊!工作关系,需要用到Oracle存储过程.我就简单看了一些教程,特此记录一 ...

最新文章

  1. 流程控制关键字——跳转结构
  2. 在 windows 7 和 MinGW 下编译 OpenOCD 过程
  3. 计算机网络是如何通信的「三」
  4. 干货:嵌入式C语言源代码优化方案(非编译器优化)
  5. 三分钟Docker-推送本地镜像到仓库
  6. 记一则js替换字符串的问题
  7. python怎么一步步调试_PyCharm入门第一步(二)——调试第一个Python应用程序
  8. Python基础学习----Requests获取url请求时间:
  9. 算法复习——带修改莫队(bzoj2453)
  10. c语言中字母后面的 是什么意思,C语言中括号里面一个字母是什么意思
  11. 红蜘蛛10013端口被占用
  12. Winform当移入控件时,鼠标变手的通用方法
  13. Zabbix启动失败,提示Zabbix-agent.servic never wrote its PID file,failing
  14. 自建数据库MySQL和云数据库Rds MySQL的优缺点
  15. 【基础算法Ⅰ】算法入门篇
  16. 基于localstorage实现增删改查功能
  17. TC工具 模拟Linux网卡限速、丢包
  18. 白话智能锁—卡片钥匙安全
  19. centos刻录工具_UltraISO刻录CentOS 7安装指南
  20. 三菱FX系列 DADD和DSUB指令使用

热门文章

  1. 轻松决绝疑难杂症:nodejs使用http报错: Request path contains unescaped characters
  2. 线程池如何确定线程数量
  3. c++ Protobuf中set_allocated引起的double free core dump
  4. Linux运行多个openssl,linux – 使用多选项解释rsa的openssl速度输出
  5. 设置linux中docker中的mysql开机自动启动
  6. android 按钮换行_自定义Android自动换行的布局
  7. Java编程:中缀表达式转后缀表达式
  8. Javascript特效:获取选中内容分享至微博
  9. Java JDK中的跳表实现
  10. 删除python读取的txt每一行尾部的\n