PL/SQL之基础篇

参考文献:《Oracle完全学习手册》第11章

1.PL/SQL概述

PL/SQL(Procedure Language/Structuer Query Language)是Oracle对标准SQL规范的扩展,全面支持SQL的数据操作、事务控制等。PL/SQL完全支持SQL数据类型,减少了在应用程序和数据库之间转换数据的操作。

构成PL/SQL程序的基本单位是程序块。程序块由过程、函数和无名块3种形式组成,它们之间可以互相嵌套。

PL/SQL的运行工具有:SQL*Plus、PL/SQL developer

2.PL/SQL结构

2.1PL/SQL程序块

PL/SQL程序块分为无名块、命名块两种。无名块指未命名的程序块,命名块指过程、函数、包和触发器等。

PL/SQL块由3个部分组成:定义部分、执行部分、异常处理部分。PL/SQL块的基本结构如下:

--DECLARE与EXCEPTION是可选的
[
DECLARE --定义部分] BEGIN --执行部分 [EXCEPTION --异常处理部分] END;

Notice:DECLARE、BEGIN、EXCEPTION后面没有分号,而END后则必须要带有分号

下面是一个PL/SQL块的一个示例:

SQL> set serveroutput on
SQL> DECLARE
  2     a NUMBER;
  3  BEGIN
  4     a:=1+2;
  5     DBMS_OUTPUT.PUT_LINE('1+2='||a);
  6  EXCEPTION
  7     WHEN OTHERS THEN
  8             DBMS_OUTPUT.PUT_LINE('出现异常');
  9  END;
 10  /
1+2=3

PL/SQL 过程已成功完成。

3.变量的数据类型

按个人的理解,在PL/SQL中,变量的数据类型可以按影响的行列来划分成以下四种类型:单行单列数据类型、单行多列数据类型、多行单列数据类型、多行多列类型。

在分别详细介绍了各种变量的数据类型的使用之前,先看一下变量声明的语法格式:

variable_name [CONSTANT] data_type NOT_NULL [DEFAULT|:=value];

3.1单行单列数据类型

单行单列数据类型也称为标量(scalar)数据类型。

标量数据类型大致可以分为以下四类:

  • Number
  • Charater
  • Data/Time
  • Boolean

表3.1显示的为Number类型,表3.2显示的为Charater类型,表3.3显示的是Data/Time及Boolean类型

表3.1 Number类型
Datatype description Subtypes description
BINARY_INTEGER

用于存储单字节整数。

要求存储长度低于

NUMBER值

 NATURAL  用于非负数
 NATURALN 只用于非负数和非NULL值 
 POSITIVE 只用于正数
 POSITIVEN 只用于正数,不能用于NULL值 
 SIGNTYPE 只有值:-1,0或1 
 NUMBER

 存储数字值,包括

整数和浮点数。可以

选择精度和刻度方式

语法:

number[([,])]

 DECIMAL(DEC)  小数
 DOUBLE PRECISION  双精度小数
 FLOAT  单精度小数
 INTEGER(INT)  整数
 NUMERIC  与NUMBER等价
 REAL  与NUMBER等价
 SMALLINT  取值范围比INT小
 PLS_INTEGER

 表示一个有符号整数

范围:-231到231

运算比NUMBER和

BINARY_INTEGER

都快

   

 

表3.2Character类型
Datatype rage subtypes description
CHAR 最大长度32767字节 CHARACTER 存储定长字符串,如果长度没有确定,缺省是1
LONG 最大长度2147483647字节   存储可变长度字符串
RAW 最大长度32767字节   用于存储二进制数据和字节字符串,当在两个数据库之间时行传递时,RAW数据不在字符集之间进行转换
LONGRAW 最大长度2147483647字节   与LONG数据类型相似,同样他也不能在字符集之间进行转换
ROWID 18字节   与数据库ROWID伪列类型相同,能够存储一个行标示符,可以将行标示符看作数据库中每一行的唯一键值。
VARCHAR2 最大长度32767字节   与VARCHAR数据类型相似,存储可变长度的字符串。声明方法与VARCHAR相同

 

表3.3Boolean及Date/Time类型
Datatype rang description
BOOLEAN TRUE/FALSE 存储逻辑值TRUE或FALSE
DATE 01/01/4712 BC 存储固定长的日期和时间值

 

在PL/SQL中,除了能使用上面说到的数据类型来声明单行单列变量之外,还可以使用%TYPE变量来声明单行单列变量. 

使用%TYPE声明的变量类型与数据表中字段的数据类型相同,当数据表中字段数据类型修改后,PL/SQL程序中相应变量的类型也自动随之改变.如:

v_name emp.ename%TYPE;

 

3.2单行多列数据类型

3.2.1 %ROWTYPE变量

%ROWTYPE变量用来存储一行数据.如下面使用%ROWTYPE类型的变量存储DEPT表中的一行数据:

set serveroutput on
DECLARE
    v_dept dept%ROWTYPE;
BEGIN
    SELECT * into v_dept FROM dept WHERE deptno=30;
    DBMS_OUTPUT.PUT_LINE(v_dept.deptno);
    DBMS_OUTPUT.PUT_LINE(v_dept.dname);
    DBMS_OUTPUT.PUT_LINE(v_dept.loc);
END;
/

 

3.2.2 自定义单行多列数据类型

自定义单行多列数据类型的语法规格如下:

TYPE record_name_type IS RECORD(
    field1_name data_type [NOT NULL][DEFAULT|:=]default_value,
    ...
);

下面是自定义单行多列数据类型的使用例子:

DECLARE
    TYPE emp_record_type IS RECORD(
        name emp.ename%TYPE,
        salary emp.sal%TYPE,
        dno emp.deptno%TYPE
    );
    emp_record emp_record_type;
BEGIN
    SELECT ename,sal,deptno INTO emp_record FROM emp WHERE empno=7788;
    /*也可以这样使用
    SELECT ename,sal INTO emp_record.name,emp_record.salary FROM emp WHERE empno=7788;
    */
    DBMS_OUTPUT.PUT_LINE(emp_record.name);
END;
/

 

 

3.3 多行单列数据类型

多行单列数据类型或者可以称其为集合变量类型.集合类型包括索引表(PL/SQL表),嵌套表(Nested Table)和变长数组(VARRAY)3种类型.下面分别详细介绍三种集合类型的异同点.

3.3.1索引表(PL/SQL表)

索引表也称为PL/SQL表,用于处理PL/SQL数组的数据类型.但是索引表与高级语言的数组是有区别的:高级语言数组的元素个数是有限制的,并且下标不能为负值;而索引表的元素个数没有限制,并且下标可以为负值,甚至可以使用VARCHAR2类型.

PL/SQL中是没有现成的索引表数据类型的,要使用索引表,必须先进行数据类型定义,其定义语法为:

TYPE type_name IS TABLE OF element_type [NOT NULL] INDEX BY key_type;

--type_name:自定义索引表数据类型的名称(IS TABLE ... INDEX表示索引表类型)
--element_type:用于指定索引表中每个元素的数据类型.如CHAR,NUMBER,VARCHAR2,emp.ename%TYPE等等.
--NOT NULL:表示不允许引用NULL元素
--key_type:用于指定索引表元素下标的数据类型,可以使用(BINARY_INTEGER,PLS_INTEGER或VARCHAR2).

 

Notice:索引表只能作为PL/SQL复合数据类型使用,而不能作为表列的数据类型使用.

Example:

DECLARE
    TYPE ename_table_type IS TABLE OF emp.ename%TYPE INDEX BY BINARY_INTEGER;
    ename_table ename_table_type;

    TYPE area_table_type IS TABLE OF NUMBER INDEX BY VARCHAR2(10);
    area_table area_table_type;
BEGIN
    SELECT ename INTO ename_table(-1) FROM emp WHERE empno=7788;
    DBMS_OUTPUT.PUT_LINE('雇员号为7788的雇员名为'||ename_table(-1));
    SELECT ename INTO ename_table(2) FROM emp WHERE empno=7369;
    DBMS_OUTPUT.PUT_LINE('雇员号为7369的雇员名为'||ename_table(2));

    area_table('北京'):=1;
    area_table('上海'):=2;
    area_table('广州'):=3;
    DBMS_OUTPUT.PUT_LINE('第一个元素:'||area_table.first);
    DBMS_OUTPUT.PUT_LINE('最后一个元素:'||area_table.last);
    DBMS_OUTPUT.PUT_LINE('元素为"北京"的下一个元素:'||area_table.next('北京'));

END;
/

 

Result:

3.3.2 嵌套表(Nested Table)

嵌套表类型与高级语言数据的区别:高级语言数组的元素下标从0或1开始,并且元素个数是有限制的,元素值是有顺序的;而嵌套表的元素下标从1开始,并且元素个数没有限制,元素值是无序的.

索引表类型与嵌套表类型的区别:索引表类型不能作为表列的数据类型使用,但嵌套表类型可以作为表列的数据类型使用.

嵌套表类型与索引表类型一样,没有现在的数据类型,要使用嵌套表类型必须首先自定义该类型,自定义嵌套表类型的语法规格如下:

TYPE type_name IS TABLE OF element_type;

--type_name:用于指定嵌套表类型的类型名.
--element_type:用于指定嵌套表内的元素的数据类型.

 

Example:在PL/SQL块中使用嵌套表

DECLARE
    TYPE ename_table_type IS TABLE OF emp.ename%TYPE;
    ename_table ename_table_type;
BEGIN
    --ename_table:=ename_table_type('','');
    SELECT ename INTO ename_table(2) FROM emp WHERE empno=7788;
    DBMS_OUTPUT.PUT_LINE('雇员名:'||ename_table(2));
END;
/

 

Example:在表列中使用嵌套表

在上面的例子中,会自动地创建表phone_table来保存phone字段的数据。

 

Example:在PL/SQL块中为嵌套表列插入数据

BEGIN
    INSERT INTO employee VALUES(1,'SCOTT',800,phone_type('12345678','87654321'));
END;
/

 

Example:在PL/SQL块中检索嵌套表列的数据

DECLARE
    phone_table phone_type;
BEGIN
    SELECT phone INTO phone_table FROM employee WHERE id=1;
    FOR i IN 1..phone_table.COUNT LOOP
        DBMS_OUTPUT.PUT_LINE('电话号码:'||phone_table(i));
    END LOOP;
END;
/

 

Example:在PL/SQL块中更新嵌套表列的数据

DECLARE
    phone_table phone_type:=phone_type('00000000','11111111');

BEGIN
    UPDATE employee SET phone=phone_table where id=1;
    /*也可以这样
    UPDATE employee SET phone=phone_type('00000000','11111111') where id=1;
    */
END;
/

 

 

3.3.3变长数组(VARRAY)

变长数组也是一种用于处理PL/SQL数组的数据类型,它也可以作为表列的数据类型使用.该数据类型与高级语言数组非常相似,其元素下标从1开始,并且元素的最大个数是有限制的.定义VARRAY的语法如下:

TYPE type_name IS VARRAY(size_limit) OF element_type [NOT NULL];

--type_name:用于指定VARRAY类型名
--size_limit:用于指定VARRAY元素的最大个数.
--element_type:用于指定元素的数据类型

 Notice:当使用VARRAY元素时,必须使用其构造方法初始化VARRAY元素

Example:在PL/SQL块中使用VARRAY

DECLARE
    TYPE ename_table_type IS VARRAY(20) OF emp.ename%TYPE;
    ename_table ename_table_type;
BEGIN
    ename_table:=ename_table_type('','');
    SELECT ename INTO ename_table(2) FROM emp WHERE empno=7788;
    DBMS_OUTPUT.PUT_LINE('雇员名:'||ename_table(2));
END;
/

 

Notice:关于变长数组在表列中的使用可以参考嵌套表,非常类似.唯一的区别是VARRAY不需要使用 NESTED TABLE子句

3.3.4三种集合类型的比较

三种集合类型的异同总结在下表中:

三种集合类型的比较
  索引表 嵌套表 变长数组 高级语言数组
元素下标

可以是负值,甚至使用VARCHAR2类型

从1开始 从1开始 从0或1开始
元素个数限制 无限制 无限制 有限制 有限制
是否需要初始化 不需要 需要 需要 需要
是否可用作表列类型 不可以 可以  可以  

 

3.3.5集合方法

集合方法是Oracle所提供的用于操作集合变量的内置函数或过程,其中EXISTS()、COUNT()、LIMIT()、FIRST()、NEXT()、PRIOR()和LAST()是函数,而EXTEND()、TRIM()和DELETE()则是过程。集合方法的调用语法如下:

collection_name.method_name{(parameters)}

 

Notice:集合方法只能在PL/SQL语句中使用,而不能在SQL语句中调用。另外集合方法EXTEND和TRIM只适合于嵌套表和VARRAY,而不适用于索引表。

下表总结了各方法的使用:

表 集合方法
方法名 用法描述 例子
EXISTS(下标值) 参数的下标值,判断某个下标的元素时否存在,存在返回TRUE,否则返回FALSE ename_table.EXISTS(1)
COUNT() 返回集合变量中的元素总个数,如果集合元素为NULL,则统计结果不包含该元素 ename_table.COUNT
LIMIT() 返回集合变量可容元素的最大个数。因为嵌套表和索引表的元素个数没有限制,所以返回NULL ename_table.LIMIT
FIRST() 返回集合变量第一个元素的下标 ename_table.FIRST()
LAST() 返回集合变量最后一个元素的下标 ename_table.LAST()
PRIOR(下标值) 返回参数中指定的下标值的前一个元素的下标 ename_table.PRIOR(2)
NEXT(下标值) 返回参数中指定的下标值的下一个元素的下标 ename_table.NEXT(1)

EXTEND

EXTEND(n)

EXTEND(n,i)

(只适用于嵌套表和VARRAY)该方法用于扩展集合变量的尺寸,并为它们增加元素。其中

EXTEND为集合变量增加一个NULL元素,EXTEND(n)为集合变量添加n个NULL元素,而

EXTEND(n,i)为集合变量增加n个元素(元素值与第i个元素相同)

ename_table.EXTEND(10,1)

TRIM

TRIM(n)

(只适合于嵌套表和VARRAY)

TRIM从集合尾部删除一个元素,而TRIM(n)从集合尾部删除n个元素

ename_table.TRIM(2)

DELETE

DELETE(n)

DELETE(m,n)

(只适合于嵌套表和索引表)DELETE用于删除集合变量的所有元素;DELETE(n)用于删除集合

变量的第n个元素;而DELETE(m,n)用于删除集合变量第m到n之间的所有元素

ename_table.DELETE(2,5)

3.4 多行多列数据类型——游标

在PL/SQL中,针对多行多列的数据类型,可以使用游标变量。

PL/SQL的游标指把从数据库中查询出来的数据以临时表的形式存放在内存中.游标可以对存储在内存中的数据进行操作,返回一条或一组记录,或者一条记录都不返回.

3.4.1游标的基本操作

游标包括两种游标:隐含游标和显式游标.隐含游标用于处理SELECT INTO和DML语句,而显式游标则专门用于处理SELECT语句返回的多行数据.

游标的基本操作有:声明游标、打开游标、提取游标和关闭游标。

下面的代码块展示了这四个基本操作:

DECLARE
    CURSOR c_emp IS SELECT * FROM EMP; --声明游标
    emp_record emp%ROWTYPE;
BEGIN
    OPEN c_emp; --打开游标
    LOOP
        FETCH c_emp INTO emp_record; --提取游标
        DBMS_OUTPUT.PUT_LINE('雇员名称:'||emp_record.ename);
    EXIT WHEN c_emp%NOTFOUND;
    END LOOP;
    CLOSE c_emp; --关闭游标
END;
/

3.4.2游标属性

游标作为一个临时表,可以通过游标的属性来获取游标状态.游标有4个常用的属性:

  1. %ISOPEN:用于判断游标是否已经打开
  2. %FOUND:用于判断游标是否找到记录
  3. %NOTFOUND:与%FOUND相反.
  4. %ROWCOUNT:返回到当前为止已经提取到的实际行数.

3.4.3参数化游标

参数化游标是指带有参数的游标,在定义了参数游标之后,当使用不同的参数值多次打开游标时,可以生成不同的结果集.参数化游标的声明语法如下:

CURSOR cursor_name(parameter) IS SELECE ...

 

Example:参数化游标的使用

DECLARE
    CURSOR emp_cursor(dno NUMBER) IS 
    SELECT ename FROM emp WHERE deptno=dno;
    v_ename emp.ename%TYPE;
BEGIN
    OPEN emp_cursor(10);
    LOOP
        FETCH emp_cursor INTO v_ename;
        EXIT WHEN emp_cursor%NOTFOUND;
        DBMS_OUTPUT.PUT_LINE(v_ename);
    END LOOP;
    CLOSE emp_cursor;
END;
/

 

3.4.4隐式游标

隐式游标就是指非PL/SQL程序中定义的,而且是在PL/SQL中使用UPDATE、DELETE或SELECT INTO语句时,Oracle系统自动分配的游标。隐式游标名称固定为SQL。隐式游标无须声明和打开,使用完后也不用关闭,所有这一切都由系统自动维护。

Example:SELECT INTO的隐式游标

DECLARE
    v_emp emp%ROWTYPE;
BEGIN
    SELECT * INTO v_emp FROM emp WHERE empno=7788;
    IF SQL%FOUND THEN
        DBMS_OUTPUT.PUT_LINE('7788的雇员名称:'||v_emp.ename);
    END IF;
END;
/

 

Example:UPDATE的隐式游标

BEGIN
    UPDATE emp SET ename='SCOTT' WHERE empno=7788;
    IF SQL%FOUND THEN
        DBMS_OUTPUT.PUT_LINE('更新成功!');
    END IF;
END;
/

 

3.4.5使用游标更新或删除数据

通过使用显式游标,不仅可以一行一行地处理SELECT语句的结果,而且也可以更新或删除当前游标行的数据。在使用游标更新或删除数据时有两点需要注意的地方:

  1. 声明游标是必须带有FOR UPDATE子句,如:
    CURSOR cursor_name IS SELECT ... FOR UPDATE;
  2. 在提取了游标数据之后,为了更新或删除当前游标行数据,必须在UPDATE或DELETE语句中引用WHERE CURRENT OF子句。如:
    UPDATE table_name SET column=... WHERE CURRENT OF cursor_name;
    DELETE table_name WHERE CURRENT OF cursor_name;

     

Example:使用游标更新数据

DECLARE
    CURSOR emp_cursor IS SELECT ename,sal FROM emp FOR UPDATE;
    v_ename emp.ename%TYPE;
    v_sal emp.sal%TYPE;
BEGIN
    OPEN emp_cursor;
    LOOP
        FETCH emp_cursor INTO v_ename,v_sal;
        EXIT WHEN emp_cursor%NOTFOUND;
        IF v_sal<2000 THEN
            UPDATE emp SET sal=sal+100 WHERE CURRENT OF emp_cursor;
        END IF;
    END LOOP;
    CLOSE emp_cursor;
END;
/

 

 

3.4.6 游标FOR循环

当使用游标FOR循环时,Oracle会隐含地打开游标、提取游标数据并关闭游标。

Example:使用游标FOR循环

DECLARE
    CURSOR emp_cursor IS SELECT * FROM emp;
    v_emp emp%ROWTYPE;
BEGIN
    FOR v_emp IN emp_cursor LOOP
        DBMS_OUTPUT.PUT_LINE(''||emp_cursor%ROWCOUNT||'个雇员'||v_emp.ename);
    END LOOP;
END;
/

 

Example: 在游标FOR循环中直接使用子查询

DECLARE
    v_emp emp%ROWTYPE;
BEGIN
    FOR v_emp IN (SELECT * FROM EMP) LOOP
        DBMS_OUTPUT.PUT_LINE('编号'||v_emp.empno||'的雇员名称:'||v_emp.ename);
    END LOOP;
END;
/

 

3.4.7 游标变量

上面提到的显式游标和隐式游标都与固定的查询语句相关联,所以称之为静态游标。游标变量与静态游标不同,它是一种动态游标,在运行期间可以与不同的查询语句相关联。

要声明游标变量,首先得创建一个游标数据类型,创建游标数据类型的语法如下:

TYPE cursor_data_type_name IS REF CURSOR [RETURN return_type];

 Example:操作游标变量

DECLARE
    TYPE emp_cursor_type IS REF CURSOR RETURN emp%ROWTYPE;
    emp_cursor emp_cursor_type;
    emp_record emp%ROWTYPE;
BEGIN
    IF NOT emp_cursor%ISOPEN THEN
        OPEN emp_cursor FOR SELECT * FROM emp WHERE deptno=10;
    END IF;
    LOOP
        FETCH emp_cursor INTO emp_record;
        EXIT WHEN emp_cursor%NOTFOUND;
        DBMS_OUTPUT.PUT_LINE('雇员名:'||emp_record.ename);
    END LOOP;
END;
/

 

4 PL/SQL的控制结构

4.1 IF语句

IF语句的语法:

IF condition1 THEN
    statement1;
ELSIF condition2 THEN
    statement2;
ELSE
    statement3;
END IF;

 

4.2 CASE语句

CASE语句语法:

CASE variable_name 
WHEN case1 THEN statement1;
WHEN case2 THEN statement2;
...
WHEN caseN-1 THEN statementN-1;
[ELSE statementN]
END CASE;

Example:CASE语句的使用

DECLARE
    grade CHAR :='B';
    appraisal VARCHAR2(20);
BEGIN
    appraisal :=
    CASE grade
        WHEN 'A' THEN ''
        WHEN 'B' THEN ''
        ELSE '不及格'
    END;
    DBMS_OUTPUT.PUT_LINE('Grade '||grade|| ' is '||appraisal);
    
    /*下面效果一样
    grade:='A';
    CASE grade
        WHEN 'A' THEN appraisal :='优';
        WHEN 'B' THEN appraisal :='良';
        ELSE appraisal :='不及格';
    END CASE;
    DBMS_OUTPUT.PUT_LINE('Grade '||grade|| ' is '||appraisal);
    
    */
END;
/

 

4.3基本循环

基本循环的语法:

LOOP
    statements
    EXIT [WHEN condition]
END LOOP;

 

4.4WHILE循环

WHILE循环语法:

WHILE condition LOOP
    statements;
END LOOP;

4.5 FOR循环

FOR循环语法

FOR loop_variable IN [REVERSE] lower_bound..upper_bound LOOP
    statements;
END LOOP;

 

Example:FOR循环的使用

DECLARE
    i INTEGER;
BEGIN
    FOR i IN REVERSE 1..3 LOOP
        DBMS_OUTPUT.PUT_LINE(i);
    END LOOP;
END;
/

 

5 异常处理

Oracle系统中的异常分为系统预定义异常和用户自定义异常。异常处理的一般语法如下:

EXCEPTION
    WHEN exception1 THEN
        statements1;
    WHEN exception2 THEN
        statements2;
    WHEN OTHERS THEN
        statements3;

5.1系统预定义异常

常用的系统预定义异常
错误信息 异常错误名称 说明
ORA-0001 Dup_val_on_index 试图破坏一个唯一性限制
ORA-0051 Timeout-on-resource 在等待资源时发生超时
ORA-0061 Transaction-backed-out 由于发生死锁事务被撤销
ORA-1001 Invalid-CURSOR 试图使用一个无效的游标
ORA-1012 Not-logged-on 没有连接到Oracle
ORA-1017 Login-denied 无效的用户名/口令
ORA-1403 NO_DATA_FOUND SELECT INTO没有找到数据
ORA-1422 TOO_MANY_ROWS SELECT INTO 返回多行
ORA-1476 Zero-divide 试图被零除
ORA-1722 Invalid-NUMBER 转换一个数字失败
ORA-6500 Stroage-error 内存不够引发的内部错误
ORA-6501 Program-error 内部错误
ORA-6502 Value-error 转换或截断错误
ORA-6504 Rowtype-mismatch 主变量和游标的类型不兼容
ORA-6511 CURSOR-ALERADY-OPEN 试图打开一个已经打开的游标
ORA-6530 ACCESS_INTO_NULL 试图为null对象的属性赋值(如一个对象没初始化时,向其内部属性赋值)

Example:NO_DATA_FOUND异常的处理

DECLARE
    v_sal emp.sal%TYPE;
BEGIN
    SELECT SAL INTO v_sal FROM emp WHERE ename='MARY';
EXCEPTION
    WHEN NO_DATA_FOUND THEN
        DBMS_OUTPUT.PUT_LINE('不存在该雇员!');
END;
/

 

5.2用户自定义异常

用户自定义异常的语法:

exception_name EXCEPTION;
PRAGMA EXCEPTION_INTO(exception_name,exception_no);

--PRAGMA关键字用于把某个异常名和异常号关联起来

在声明了自定义异常后,便可以使用RAISE语句显式触发异常了。

Example:触发用户自定义异常

DECLARE
    e_no_employee EXCEPTION;
    PRAGMA EXCEPTION_INIT(e_no_employee,-2291);
BEGIN
    UPDATE emp SET deptno=10 WHERE empno=1111;
    IF SQL%NOTFOUND THEN
        RAISE e_no_employee;
    END IF;
EXCEPTION
    WHEN e_no_employee THEN
        DBMS_OUTPUT.PUT_LINE('该雇员不存在!');
END;
/

 

 

5.3异常函数

  1. SQLCODE()和SQLERRM()
    SQLCODE()用于返回Oracle错误号,而SQLERRM()用于返回该错误号对应的错误消息。

  2. RAISE_APPLICATION_ERROR
    该过程用于在 PL/SQL应用程序中自定义错误消息。该过程只能在(过程、函数、包、触发器)中使用。

Example:SQLCODE()和SQLERRM()的使用

DECLARE
    v_ename emp.ename%TYPE;
BEGIN
    SELECT ename INTO v_ename FROM emp WHERE deptno=10;
    DBMS_OUTPUT.PUT_LINE('雇员名:'||v_ename);
EXCEPTION
    WHEN NO_DATA_FOUND THEN
        DBMS_OUTPUT.PUT_LINE('雇员不存在!');
    WHEN OTHERS THEN
        DBMS_OUTPUT.PUT_LINE('错误号:'||SQLCODE);
        DBMS_OUTPUT.PUT_LINE(SQLERRM);
END;
/

 

Example:RAISE_APPLICATION_ERROR的使用(略)

  RAISE_APPLICATION_ERROR('-20001','该雇员无补助');

 

 

 

posted on 2012-08-26 23:51  TimLeung  阅读(21851)  评论(0编辑  收藏  举报

导航