PL/SQL之基础篇
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类型
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 都快 |
Datatype | rage | subtypes | description |
CHAR | 最大长度32767字节 | CHARACTER | 存储定长字符串,如果长度没有确定,缺省是1 |
LONG | 最大长度2147483647字节 | 存储可变长度字符串 | |
RAW | 最大长度32767字节 | 用于存储二进制数据和字节字符串,当在两个数据库之间时行传递时,RAW数据不在字符集之间进行转换 | |
LONGRAW | 最大长度2147483647字节 | 与LONG数据类型相似,同样他也不能在字符集之间进行转换 | |
ROWID | 18字节 | 与数据库ROWID伪列类型相同,能够存储一个行标示符,可以将行标示符看作数据库中每一行的唯一键值。 | |
VARCHAR2 | 最大长度32767字节 | 与VARCHAR数据类型相似,存储可变长度的字符串。声明方法与VARCHAR相同 |
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个常用的属性:
- %ISOPEN:用于判断游标是否已经打开
- %FOUND:用于判断游标是否找到记录
- %NOTFOUND:与%FOUND相反.
- %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语句的结果,而且也可以更新或删除当前游标行的数据。在使用游标更新或删除数据时有两点需要注意的地方:
- 声明游标是必须带有FOR UPDATE子句,如:
CURSOR cursor_name IS SELECT ... FOR UPDATE;
- 在提取了游标数据之后,为了更新或删除当前游标行数据,必须在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异常函数
- SQLCODE()和SQLERRM()
SQLCODE()用于返回Oracle错误号,而SQLERRM()用于返回该错误号对应的错误消息。 - 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','该雇员无补助');