1、网络数据库,内蒙古工业大学管理学院,王建国,(第九讲),2019/8/17,6.1 PL/SQL 块结构,第六章 PL/SQL程序结构,PL/SQL程序结构共包括五部分。,6.2 PL/SQL 定义部分,6.3 PL/SQL 可执行部分,6.4 PL/SQL 控制结构,6.5 异常处理,6.1 PL/SQL块结构,第六章 PL/SQL程序结构 之,2019/8/17,6.1 PL/SQL 块结构,基本块结构嵌套的块结构,2019/8/17,6.1.1 PL/SQL 基本块结构,Declare-说明部分 (可选部分) begin-语句执行部分 (必需部分) exception-异常处理部分 (可
2、选部分) end; /,2019/8/17,6.1.2 PL/SQL 嵌套的块结构,例:Declare-说明部分Begin-主块的语句执行部分Begin-子块的语句执行部分Exception-子块的异常处理部分End;Exception-主块的异常处理部分End;,PL/SQL块中可包含子块,子块可位于PL/SQL块中的任何部分。子块也可是一条PL/SQL命令。,6.2 PL/SQL定义部分,第六章 PL/SQL程序结构 之,6.2 PL/SQL定义部分,6.2.1 PL/SQL标识符,6.2.2 PL/SQL数据类型,6.2.3 声明变量,2019/8/17,6.2.1 PL/SQL标识符,
3、在PL/SQL块中引用的所有标识符,都必须在PL/SQL的定义部分明确定义其数据类型。定义部分是包括在DELARE和BEGIN之间的部分,每条语句用;结束。,语法:标识符CONSTANT 数据类型NOT NULL: =PL/SQL表达式;其中: =表示给变量赋值,2019/8/17,注意:1)每行只能定义一个标识符2)如果定义时加上CONSTANT,表示所定义的标识符是一个常量,必须为它赋初值3)标识符的命名规则与SQL命名规则基本相同,必须以字母开头,且不区分大小写4)如果定义的标识符不能为空,必须加上NOT NULL,且必须赋初值5)为标识符赋值使用:=,默认初始值为空值,6.2.1 PL
4、/SQL标识符,2019/8/17,6.2.1 PL/SQL标识符,标识符用来命名PL/SQL对象,如:变量、游标、类型和子程序 标识符由字母开头,后面跟随任何字符序列,包括字母、数字、货币符号、下划线字符和#号字符。其他字符是非法的。 一个标识符的最大长度是30个字符 字符不区分大小写 不能是ORACLE的保留字,2019/8/17,6.2.2 数据类型,数据类型,2019/8/17,6.2.2.1 数字型,用来存储整数或实数。NUMBER、BINARY_INTEGER、PLS_INTEGER NUMBER-存储整数和浮点数 BINARY_INTEGER -存储带符号的整数值,溢出时不发生错
5、误 PLS_INTEGER -存储带符号的整数值,溢出时发生错误 例如:V_NUM NUMVER(5);v_binarynum binary_integer;,2019/8/17,6.2.2.2字符型,用于存储字符串或字符数据。包括VARCHAR2、CHAR、LONG、NCHAR、NVARCHAR2 VARCHAR2-存储可变长度的字符串 CHAR -存储固定长度的字符串 LONG -存储可变长度的字符串,其最大长度是32760字节 NCHAR、NVARCHAR2 -NLS字符类型用于存储来自不同于PL/SQL语言的字符集中的字符集 例如:V_CHAR VARCHAR2(20),2019/8/
6、17,6.2.2.3-4 日期型、布尔型,布尔型布尔型的类型为BOOLEAN。布尔变量在PL/SQL控制结构中使用,BOOLEAN变量只能存储TRUE、FALSE、NULL值。 例如:V_BOOLEAN BOOLEAN,日期型用于存储日期和时间信息,包括世纪、年、月、天、小时、分钟和秒。唯一类型为DATE 例如:V_DATE DATE,2019/8/17,6.2.2.5 原始型,用来存储二进制数据。包括RAW、LONG RAW RAW-存储定长的二进制数据。类似CHAR型,但不在字符集之间进行转换。 LONG RAW-与LONG类似,最大长度为32760字节,但不在字符集之间进行转换。例如:
7、V_LONG LONG;,6.2.2.6 复合类型、%TYPE及%ROWTYPE,复合类型的变量包含一个或多个标量变量。包括: RECORD TABLE VARRAY %TYPE和%ROWTYPE用来声明与表的列相匹配的变量。,RECORD提供了处理分立的但又是作为一个整体单元的相关变量的一种机制。存储单行多域结构数据。 例如: type t_record is record( studentid number(5), name varchar2(8); 定义基于t_record的记录变量: stu t_record 引用stu时要指明该记录的内部变量: stu.studentid:=9800
8、1,%TYPE一个变量的类型用另一个已经定义的变量的类型定义,或用表的某一列的类型来定义。 例如: bprint number v_book bprint%typev_empno emp.empno%type,%ROWTYPE变量的类型参考基表中记录的类型。 例:V_REC EMP%ROWTYPE引用: V_REC.EMPNO :=1001 V_REC.ENAME:=TOM,6.2.2.6 复合类型、%TYPE及%ROWTYPE(续),6.2.3 声明变量,如果希望一个变量的类型与某个变量或与数据库基表中某个列的数据类型一致,而又不知道该变量或该列的数据类型,这时应该使用%TYPE 例1 声明
9、一个变量Student_name,使其类型基于另一个变量Teacher_name。 DECLARE Teacher_name char(10); Student_name Teacher_name%TYPE BEGIN .,6.2.3 声明变量(续),例2 声明一个变量No,使其与表EMP中的EMPNO的类型一致。 DECLARE No EMP.EMPNO%TYPE BEGIN . 注意:表中某一列的表示方法应采用基表名.列名的形式。,例3 声明一个变量,存放一个学生的有关信息。 DECLARE TYPE STUDENT IS RECORD ( ID NUMBER(4) NOT NULL :=
10、1001,NAME CHAR(10) ,SEX BOOLEAN ,BIRTHDAY DATE,PHYSICS NUMBER(3),CHEMISTRY NUMBER(3); STU STUDENT; BEGIN .,6.2.3 声明变量(续),例4 声明一个变量,其结构与表EMP的数据结构一致。 DECLARE EMP_VALUE EMP%ROWTYPE; BEGIN .,6.3 PL/SQL可执行部分,第六章 PL/SQL程序结构 之,2019/8/17,6.3 PL/SQL可执行部分,PL/SQL块的可执行部分是PL/SQL块必须具备的。,2)数据查询、数据操纵和事务控制语句,1)变量赋值语
11、句,2019/8/17,6.3.1 变量赋值,变量赋值格式:变量名 := 常量 或PL/SQL表达式; 变量的赋值可以在DECLARE段中,也可以在PL/SQL语句执行部分赋值。,2019/8/17,6.3.1 变量赋值(续),给变量赋值主要有3种情况: 1)标量型变量赋值 例如:TEACHER_NAME := LIU; 2)PL/SQL RECORD类型变量赋值 例:STUDENT.NAME:=FAN;STUDENT.SEX:=TRUE;STUDENT.PHYSICS:=90;,2019/8/17,6.3.1 变量赋值(续),给变量赋值主要有3种情况: 3)%ROWTYPE型变量的赋值可采用
12、两种方式: (1)使用与RECORD类型相同的方法进行赋值 例: EMP_VALUE.ENAME=BLACK;EMP_VALUE.EMPNO:=9999;EMP_VALUE.DEPTNO:=10; (2)使用SELECT语句为整个变量赋值 例: SELECT * INTO EMP_VALUEFROM EMPWHERE ENAME:=FAN;,2019/8/17,6.3.2 对数据库访问,PL/SQL块的可执行部分不仅可以对变量进行赋值,而且可以对数据库进行访问。,2019/8/17,6.3.3 空值处理,判断一个变量的值是否为空的正确写法:if my_var is null thenend i
13、f; 不能写成: my_var = null,NULL+ = NULL NULL = NULL NULL | 字符串 = 字符串,6.4 PL/SQL控制结构,第六章 PL/SQL程序结构 之,2019/8/17,6.4 PL/SQL的控制结构,6.4.1 条件语句,6.4.2 循环,6.4.3 GOTO语句和块标号,2019/8/17,6.4.1 条件语句,1)IF_THEN_ELSE语句 语法结构: IF 条件 THEN语句1;语句2;ELSE语句N;语句N+1;END IF;,PL/SQL提供两种形式的条件控制语句:,2019/8/17,2)IF_THEN_ELSIF语句 IF 布尔表达
14、式1 THEN语句序列1;. ELSIF 布尔表达式2 THEN语句序列2;- ELSE语句序列3; END IF; / 可根据需要写任意多的ELSIF子句.,6.4.1 条件语句(续),PL/SQL提供两种形式的条件控制语句:,2019/8/17,6.4.1 条件语句(续),例1:修改EMP表中7788雇员的奖金,如果他是销售人员,就把奖金改为1000元,其他工种改为500元。,SAMPLE,6.4 PL/SQL控制结构,第六章 PL/SQL程序结构 之,2019/8/17,6.4 PL/SQL的控制结构,6.4.1 条件语句,6.4.2 循环,6.4.3 GOTO语句和块标号,2019/8
15、/17,6.4.2 循环,循环分四种类型:1. 简单循环2. WHILE循环3. 数字式循环4. 游标式FOR循环,退出循环的语法有两种:1. EXIT WHEN CONDITION;2. IF CONDITION THENEXIT;END IF;,2019/8/17,6.4.2.1 简单循环,LOOP 语句序列; END LOOP;,例1 求5以内的自然数之和,程序及运行结果如下,2019/8/17,例1 求5以内的自然数之和:DECLARE control_var number(2) := 0;BEGIN :sum1 :=0;Loop If control_var 5 thenexit;E
16、nd if; :sum1 :=:sum1+control_var;control_var := control_var+1;End loop;END;/,6.4.2.1 简单循环(续),用第二种退出循环的方法改写上例如下:,sum,2019/8/17,6.4.2.2 WHILE循环,用WHILE循环重新改写例1:DECLARE control_var number(2) := 0;BEGIN :sum1:=0;While control_var 5 loop :sum1 :=:sum1+control_var; control_var := control_var+1;End loop;END
17、;/,WHILE condition LOOP 语句序列; END LOOP;,2019/8/17,6.4.2.3 数字式FOR循环,语法: FOR loop_counter INREVERSE low_boundhigh_bound LOOP 语句序列; END LOOP; 其中: IN-表示从小值到大值IN REVERSE-表示从大值到小值,用FOR循环重新编写我们的例1:DECLARE control_var number(2) :=1;sum1 number(3):=0;BEGINFOR control_var IN 15 LOOP sum1:=sum1+control_var;End
18、 loop;END;/,2019/8/17,6.4.3 GOTO语句和块标号,PL/SQL 提供了GOTO语句,语法是:GOTO label; 这里label是PL/SQL块中用双箭头括起来的标签。当执行GOTO语句时,控制会立即无条件地转到由标签标识的语句。,2019/8/17,6.4.3 GOTO语句和块标号,例1 向表temp_table插入50行记录。 Declare v_counter binary_integer:=1; begin loopinsert into temp_table values(v_counter,loop counter);v_counter:=v_coun
19、ter+1;if v_counter 50 thengoto endofloop;end if; end loop; insert into temp_table(char_col) values(done!); end; /,2019/8/17,6.4.3.1为循环设定标签,例: begin for v_outerindex in 150 loop for v_innerindex in 210 loop exit outer; end if; end loop inner; end outer;,循环本身是可以被设定标签的。如果进行了设定,则可以在EXIT语句中使用该标签指明要退出哪个循环
20、。,2019/8/17,6.4.3.2 块标号,例: declare deptno number:=20; begin declare deptno number:=10; begin update emp set sal=sal*1.1 where deptno=sample.deptno; commit; end; end; /,为每一个PL/SQL块加一个块的标号,解决变量的二义性问题,6.4.3.3 对于GOTO的限制,从一个IF子句跳转到另一个子句中是非法的。,对于块、循环或IF语句而言,想从外层跳到内层是非法的。,从一个异常处理块内部跳转到当前块是非法的。,例1 下面的语句非法。
21、BEGINGOTO innerblock;BEGINEND;GOTO innerblock;. END;,6.4.3.3 对于GOTO的限制(续),例2 下面的语句非法。 BEGIN IF X3 THEN . GOTO ELSE END IF; END;,例 下面的语句非法。 DECLAREV_ROOM ROOMS%ROWTYPE; BEGINSELECT * INTO V_ROOM FROM ROOMS WHERE ROWID=1; INSERT INTO TEMP_TABLE(CHAR_COL.) VALUES(FOUND A ROW); EXCEPTIONWHEN NO_DATA_FOU
22、ND THENGOTO INSERT; END; /,6.4.3.3 对于GOTO的限制(续),6.5 PL/SQL异常处理,第六章 PL/SQL程序结构 之,6.5 PL/SQL异常处理,6.5.1 异常处理的概念,6.5.2 系统预定义的常用异常情况,6.5.3 用户自定义的异常情况,2019/8/17,6.5.1 异常处理的概念,异常处理方法是程序对运行时刻错误作出反应并进行处理的方法。语法如下:EXCEPTIONWHEN 异常情况1 THEN语句序列1;WHEN 异常情况2 THEN语句序列2;-WHEN OTHERS THEN语句序列3;END;,编辑PL/SQL程序时难免会有一些错
23、误,有些未知的错误只能在运行过程中才可能出现,这些错误称为异常。,异常情况分系统预定义、用户自定义两种,6.5.2 系统预定义的常用异常情况,INVALID_CURSOR 非法的游标操作 NOT_LOGGER_ON 没有连接到ORACLE LOGIN_DENIED 无效的用户名/口令 NO_DATA_FOUND 没有找到数据 TOO_MANY_ROWS SELECT语句结果多行 ZERO_DIVIDE 被零除,使用系统预定义的异常情况的例子 set serveroutput on declare person_no emp.empno%type; person_name emp.ename%t
24、ype; begin select empno,ename into person_no,person_name from persons where no7788; exception when no_data_found thendbms_output.put_line(no data found); when too_many_rows thendbms_output.put_line(too many rows); end;,6.5.2 系统预定义的常用异常情况,SAMPLE,6.5.3 用户自定义的异常情况,在程序的异常处理部分对定义的异常情况进行处理,用户定义的异常情况处理分三步:
25、,定义异常情况,-触发异常情况,定义异常情况,例:my_exception exception;,触发异常情况,当一个异常情况相关的错误出现时,就会引发该异常情况。用户定义的异常情况是通过显式使用RAISE语句来引发的,而系统预定义的异常情况是当相关的ORACLE错误发生时被隐式触发的。,触发用户自定义的异常情况的例子:RAISE my_exception ;,处理异常情况,在程序的异常处理部分对定义的异常情况进行处理。,例如:WHEN my_exception THEN-,例:查询7900雇员的工资,如果工资少于1000元,触发异常情况。 CREATE TABLE ERRTABLE(NO N
26、UMBER(5),MESS VARCHAR2(50); DECLAREemp_no emp.empno%type;emp_sal emp.sal%type;too_low exception; BEGINselect empno,sal into emp_no,emp_sal from empwhere empno=7900;if emp_sal 1000 thenraise too_low;end if; EXCEPTIONwhen no_data_found theninsert into errtable(no,mess)values(emp_no,No data found!);whe
27、n too_low theninsert into errtable values(emp_no,The salary is too low!);when others thennull; END; /,6.5.3 用户自定义的异常情况(续),SAMPLE,6.5.3 用户自定义的异常情况自定义错误号,用户可以将定义好的异常与标准的ORACLE错误联系起来,在DECLARE中定义了一个命名的异常情况后,这条异常就有了一个错误号,范围是-20000到-20999之间,共1000个。,定义的语法: PRAGMA EXCEPTION_INIT(异常名,错误代码);,例: declare e_miss
28、ingnull exception; pragma exception_init(e_missingnull,-20005); begininsert into students(snum) values(null); exception when e_missingnull then insert into errtable(info) values(ora-20005 occur); end; /,2.5.3 用户自定义的异常情况自定义错误号,6.5.3 用户自定义的异常情况创建错误信息,语法:RAISE_APPLICATION_ERROR(错误号码,错误信息) 系统 变量SQLCODE可以返回错误号,SQLERRM可以返回错误信息,