应用于Web的面向对象关系型数据库管理系统Oracl.ppt
wnt 2000(C)copyright,1,应用于Web的面向对象关系型数据库管理系统:Oracle,PL/SQL 简介,2,本章目标,PL/SQL 简介 PL/SQL 功能 变量和常量对变量赋值 PL/SQL 结构 异常简介 预定义的异常 用户定义的异常,3,PL/SQL 简介,SQL 是当今最为强大的数据检索机制之一 它被认为是数据库技术的颠峰 SQL 并不能完成一个过程语言所能完成的所有任务 PL/SQL 的出现将 SQL 的强大功能和过程语言的灵活性结合在了一起,4,PL/SQL 简介(续),PL/SQL 是 SQL 的扩展 它是一种包含了过程语句和命令以及 SQL 命令的应用程序开发语言此语言消除了数据库技术和过程编程语言之间的障碍,5,PL/SQL 简介(续),它使用复杂的 Oracle RDBMS中的工具并扩展了标准的 SQL 数据库语言 它允许使用所有的 SQL DML语句以及事务处理语句 它允许使用诸如迭代循环和条件分支等流控制语句来处理数据,6,PL/SQL 功能,消除了技术和过程语言之间的障碍扩展了标准的 SQL 数据库语言植根于 SQL使用控制、循环和分支等过程技术 灵活、强大、简单易学,7,PL/SQL 功能(续),它支持诸如游标操作、异常、函数和事务命令的 SQL 它不支持 DDL 和 DCL它在逻辑上对语句分组并可将其作为单一程序块发送到 RDBMS事务处理语言提供了过程解决方案,8,PL/SQL 功能(续),变量和常量、强大的错误处理和函数 每个 PL/SQL 语句调用 SQL 并增强了性能 减少了客户机/服务器环境中的网络流量 减少了应用程序与 RDBMS 之间的通信,9,PL/SQL 功能(续),对诸如 SQL*Forms 等非过程工具增加了功能 使用 SQL*Forms 的开发人员可以输入使用单一触发器的整个 PL/SQL 程序块 用 PL/SQL 开发的应用程序可以移植到任何计算机硬件和运行 Oracle 的操作系统%TYPE 属性基于列定义的声明提供了与数据词典的集成,10,PL/SQL 结构,一个标准 PL/SQL 代码段称作程序块 一个程序块是由三个部分或节构成的 声明部分 可执行部分 异常处理部分,11,PL/SQL 结构(续),12,PL/SQL 结构(续),声明部分 定义对象的可选部分 可执行部分 构成可执行语句的必要部分 异常处理部分 构成错误处理代码的可选部分,13,PL/SQL 结构(续),DECLARE表示程序块声明部分的开始 声明对于程序块而言是局部的 BEGIN表示程序块可执行部分的开始 END表示程序块的结束,14,PL/SQL 结构(续),可以将语句在 PL/SQL 中分组 命名组称为子程序 未命名组是匿名程序块 程序块可以包括称为嵌套程序块的多个块 只允许在可执行程序和异常处理部分进行嵌套 最多允许 200 级嵌套,15,PL/SQL 结构(续),可以用任何编辑器编写 PL/SQL程序,并将其保存为具有.sql 扩展名的文件也可以使用 SQL*Plus中的“ED”命令创建 PL/SQL 程序文件使用“”命令执行 PL/SQL 程序文件,16,变量,可以使用变量存储查询结果以便以后处理,或使用变量来计算要插入到数据库表中的值 在 SQL 或 PL/SQL语句中,都可以将 PL/SQL变量用于表达式的任何位置在其他语句(包括声明性语句)中对其引用前必须先进行声明,17,变量(续),是通过指定数据类型的名称来声明的 可以被声明为任何 Oracle 内部数据类型示例 oldfare NUMBER(5);m_name VARCHAR(15);cont BOOLEAN;,18,常量,除了必须添加关键字 CONSTANT 并赋值外,常量的声明方式与变量非常相似示例 bonus_multiplier CONSTANT NUMBER(3,2):=0.33;,19,使用属性声明,PL/SQL 对象(如变量和常量)和数据库对象(如列和表)与某些属性关联 这些属性可以用于简化变量和常量声明,20,%TYPE 属性,提供变量或列的数据类型 在对引用到数据库中的列的变量进行声明时有用 需要知道列的确切数据类型 如果列定义发生变化,则变量的数据类型在运行时也将随之更改 示例 oldfare fare.first_fare%TYPE;newfare oldfare%TYPE;,21,%ROWTYPE属性,当记录变量具有与表或视图中的行或从游标获取的行相同的结构时有用 记录中的字段具有与表/视图中的列相同的名称和数据类型 示例 emp_rec employee%ROWTYPE;可以使用下列属性引用特定字段 emp_rec.emp_num;,22,使用赋值操作符进行赋值,通过使用赋值操作符“:=”,将变量放在“:=”左侧,而将包含数据量、变量、算术操作符或 PL/SQL 函数调用的表达式放置在右侧来对变量赋值示例 emp_rec.dept_code:=MKTG;num:=100;,23,使用 SELECT INTO 进行赋值,还可以按如下方法使用 SELECT INTO 对变量赋值 SELECT INTO FROM WHERE;示例 SELECT first_fare INTO oldfareFROM fare WHERE route_code=SAN-LOU;,24,使用 SELECT INTO 进行赋值(续),SELECT 语句执行后,将出现下列情况之一 只检索了一行 检索了多行 不检索任何行 仅当它检索一行时,SELECT 才成功操作 其他两种情况将导致错误并产生异常处理程序,25,接受用户输入的值,使用“mcode”是绑定变量,不应该声明,但是需要声明 mbranch_code,26,条件控制,选择结构测试某个条件,然后根据条件在两序列语句中选择一列执行 有三种语句形式 IF-THENIF-THEN-ELSEIF-THEN-ELSIF,27,IF-THEN 结构,仅当条件值为 TRUE 时,才执行语句序列 如果条件判定为 FALSE 或 NULL,则不执行任何操作 这两种情况下控制都将转到 IF-THEN structure 结构后的下一个语句 IF THEN语句;END IF;,28,IF-THEN-ELSE 结构,仅当条件值为 FALSE 或 NULL 时,才执行 ELSE 子句中的语句序列 IF THEN语句;ELSE语句;END IF;,29,IF-THEN-ELSIF 结构,此结构可以从几个互斥的、排它的选项中选择操作行为 IF 语句可以具有任意数目的 ELSIF 子句 最终的 ELSE 是可选项将按自顶向下的顺序逐项检测条件,30,IF-THEN-ELSIF 结构(续),IF THEN语句;ELSIF THEN语句;ELSIF THEN语句;ELSE语句;END IF;,31,循环控制,使用 LOOP 或 GOTO 语句可以重复或跳过程序块的选取部分 有三种形式的 LOOP 语句 LOOPWHILE-LOOPFOR-LOOP,32,LOOP 语句,LOOP 将重复某些语句序列 被重复的语句位于关键词 LOOP 和 END LOOP 之间 每执行一次循环迭代过程,就执行一次语句序列,然后控制又回到循环的开始位置 LOOP语句;END LOOP;,33,EXIT 语句,如果不需要或不可能让循环进一步处理,用于完成循环 有两种形式的 EXIT 语句EXITEXIT-WHEN,34,EXIT 语句(续),强制循环无条件完成 必须放在循环内 LOOP语句;IF THENEXIT;-立即退出循环 END IF;END LOOP;-控制到此处恢复,35,EXIT-WHEN 语句,允许循环有条件完成 在遇到 EXIT 语句时对 WHEN 子句中的条件进行判断 如果判定条件为 TRUE,则循环完成 语句;EXIT WHEN;END LOOP;,36,WHILE-LOOP 语句,将条件与 LOOP-END LOOP 中的语句序列相关联 在每次循环前判定条件 如果条件值为 TRUE,就执行一次语句序列,然后控制又回到循环的开始位置 如果条件判定为 FALSE 或 NULL,则绕过循环,并且控制转到下一个语句,37,WHILE-LOOP 语句(续),循环执行的次数取决于条件且只有完成循环后才可知 WHILE LOOP语句;END LOOP;,38,FOR-LOOP 语句,循环在指定的整数范围内进行 对于一定范围内的每个整数,都执行一次该语句此范围为循环架构的一部分,它位于 FOR 和 LOOP 之间 当首次进入循环时,范围只判定一次 每执行一次循环,循环计数器就会增加,39,FOR-LOOP 语句(续),不能为循环计数器赋值 在运行时可以动态分配循环范围 FOR IN 逆转 lower_bound.higher_bound LOOP语句;END LOOP;,40,GOTO 语句,无条件分支到一个标签 执行时,语句将更改 PL/SQL 程序块的控制流编制 GOTO 语句代码需要有两个部分定义标签名称 使用 GOTO 语句将控制转到标签,41,GOTO 语句(续),标签名称 可以选择将其用于命名 PL/SQL程序块或程序块中的语句使用尖括号进行定义()IF 条件 THEN语句;END IF;语句;GOTO if_fare_label;,42,GOTO 语句(续),在下列位置可以使用 GOTO 语句来转移控制 从程序块到可执行语句 从异常处理程序分支到封闭的程序块,43,GOTO 语句(续),不允许在下列位置使用 GOTO 语句来转移控制从某个 IF 语句或循环子句内转到其他语句从封闭程序块转到某个子程序块从异常处理程序转到当前程序块子程序之外转到关键字,44,NULL 语句,明确指定不进行操作(例如,除了将控制转移到下一个语句而不进行任何操作)它提高了可读性 IF newfare 90 THEN语句;ELSENULL;END IF;,45,注释的使用,添加注释可以提高程序的可读性并帮助理解PL/SQL 支持两种注释样式单行注释可以在行中的任何地方以双分号(-)开始可以扩展到行尾多行注释这些注释以/*开始并以*/结束 可以跨越多行,46,异常简介,错误条件称为异常错误发生时,产生异常,这些异常包括常规执行停止并且控制转移到了 PL/SQL 程序块或子程序的异常处理部分 要处理产生的异常,需要编写单独的称作异常处理程序的例程,47,异常介绍(续),有两类异常预定义异常(内部异常)用户定义的异常,48,异常的范围规则,不能在同一程序块两次声明异常,但可以在两个不同的程序块声明同一个异常在程序块中声明的异常对于程序块是局部的,而对于所有子程序块则是全局的封闭的程序块不能引用在子程序块中声明的异常,因为程序块只能引用局部或全局异常,49,预定义异常,在 PL/SQL 程序块验证一个 Oracle 规则或超过了系统依赖限制时隐式地发生 每个 Oracle 错误都有一个编号,但必须通过名称来处理异常 PL/SQL 预定义了某些通用的 Oracle 错误作为异常 PL/SQL 在全局范围内声明这些预定义异常,50,预定义异常(续),某些预定义的异常 CURSOR_ALREADY_OPENNO_DATA_FOUNDTOO_MANY_ROWSVALUE_ERRORZERO_DIVIDE可以使用“OTHERS”异常来处理所有未在程序块中定义的其他错误,51,预定义异常(续),示例 异常WHEN NO_DATA_FOUND THENDBMS_OUTPUT.PUT_LINE(Route code not found);WHEN OTHERS THEN语句;END;可选的 OTHERS 异常处理程序总是程序块中的最后一个处理程序,52,预定义异常(续),一个程序块仅可以有一个 OTHERS 处理程序 使用 OTHERS 处理程序将确保可以处理所有异常每次在程序块异常处理部分中仅可以激活一个异常 如果嵌套程序块没有异常处理程序,则执行下一个外部程序块的异常处理程序,53,预定义异常(续),可以在一个异常处理程序中通过关键字 OR 将异常分隔开来处理多个异常Exception WHEN NO_DATA_FOUND OR TOO_MANY_ROWS THEN语句;WHEN OTHERS THEN语句;END;,54,用户定义的异常,需要在 PL/SQL 程序块、子程序或数据库触发器的声明部分对用户定义的异常进行定义 可以通过将异常命名并定义为数据类型 EXCEPTION 进行声明 示例 DECLAREpast_due EXCEPTION;zero_error EXCEPTION;,55,用户定义异常(续),与变量相同,用户定义的异常必须具有名称 与变量不同,不能为用户定义的异常赋值,并且不能将其用于 SQL 语句 需要使用 RAISE 语句明确产生,56,用户定义异常(续),仅当出现的错误无法完成处理时,程序块才 RAISE 一个异常可以在表达式范围内的任意位置对给定表达式的 RAISE 语句进行编码IF mrec.ss_fare=0 THENRAISE zero_error;END IF;,57,用户定义异常(续),处理程序中发生的异常被立即传送到封闭的程序块,将对其进行搜索为新产生的异常查找一个处理程序 从这里开始,将按常规方式发送异常 要重新产生一个异常,应在局部处理程序中放入一个 RAISE 语句,58,异常处理程序,用于捕获已产生的异常 由 WHEN 子句构成,指定一个异常,后跟一个当异常产生时要执行的语句序列当异常在游标的 FOR 循环中产生时,游标将被隐式地关闭控制不返回到开始执行的地方,59,错误函数,可以在异常处理程序中使用两个错误函数SQLCODE用于查找发生了什么错误 SQLERRM用于获得错误消息不能在 SQL 语句中直接使用必须将这些值赋给 SQL 语句中的局部变量,60,错误函数(续),SQLCODE对于预定义的异常错误返回一个负数并将控制传回给处理程序 为“未找到数据”错误返回+100对于用户定义的异常 返回+1,61,错误函数(续),SQLERRM对于预定义的异常 返回与发生的错误相关的消息 消息以错误代码开始 对于用户定义的异常 返回“User-Defined Message”消息 还将接受一个错误号,并返回与该错误号相关的消息,62,错误函数(续),DECLAREmsqlcode NUMBER;msqlmsg CHAR(255);BEGIN语句;EXCEPTIONWHEN OTHERS THENmsqlcode:=SQLCODE;msqlmsg:=SQLERRM;DBMS_OUTPUT.PUT_LINE(Error occurred-|TO_CHAR(msqlcode)|msqlmsg);END;,63,应用于Web的面向对象关系型数据库管理系统:Oracle,游标和复合数据类型,2,64,本章目标,游标简介游标类型隐式游标显式游标游标功能 定义游标操纵游标 游标属性,65,本章目标(续),游标 FOR 循环参数化游标UPDATE OF 和 CURRENT OF 的游标 PL/SQL 表 PL/SQL 记录,66,游标简介,要处理 SQL 语句,PL/SQL 打开一个称作环境区域的工作区 PL/SQL 使用该区域执行 SQL 语句和存储处理信息 称作“游标”的 PL/SQL 结构允许您命名环境区域,访问其信息及在某些情况下控制其处理过程,67,游标简介(续),查询返回多行时,可以将游标显式地定义为 在查询所返回的首行之外的处理 对当前正在处理的行进行跟踪 由多行查询返回的行集称作活动集,68,游标类型,PL/SQL 使用两类游标 隐式游标由 Oracle 自动定义并打开,用于处理每个 SQL语句最近打开的环境区域被称为“SQL%”游标 显式游标如果查询返回多行,则可定义显式游标来对当前正在处理的行进行跟踪,69,游标功能,游标名是一个未声明的标识符,仅用于引用查询 不能对游标赋值,也不能在表达式中使用游标名显式游标可以有参数游标参数可以出现在查询中常量出现的任何位置上 可以将游标参数初始化为默认值,70,游标的功能(续),可以将实参的不同值传递到游标,按需要采用或替换默认值游标参数的范围对于游标来讲是局部变量 当游标为 OPENED 时,游标参数的值可以用于相关的查询,71,定义游标,可以通过在 PL/SQL 程序块的声明部分命名游标或将它与某个查询关联来定义一个游标CURSOR IS;示例CURSOR emp_cur ISSELECT empno,ename,job,salFROM emp;,72,操纵游标,可以使用下列语句操纵游标OPENFETCHCLOSE在使用 OPEN、CLOSE 或 FETCH 语句引用这些语句之前必须对游标进行声明,73,OPEN 语句,初始化或打开游标 在查询返回任何行之前必须打开游标 打开游标将执行查询并识别活动集合 OPEN 示例OPEN emp_cur;,74,FETCH 语句,一次只能在一个活动集合中检索行 可以重复执行,直到检索到了所有行 FETCH INTO var1,varN;ORFETCH INTO record_variable;示例FETCH emp_cur INTO mrec;,75,CLOSE 语句,关闭游标并让活动集合成为未定义内容 CLOSE;示例CLOSE emp_cur;只要游标关闭,可以通过使用 OPEN 语句重新打开它,76,显式游标的属性,每个游标有四个属性可以用于访问游标的环境区域%NOTFOUND%FOUND%ROWCOUNT%ISOPEN要使用这些属性,只要简单地将它们添加到游标名后即可,77,显式游标的属性(续),%NOTFOUND如果因为没有多行而使最后的 FETCH 失败,则判定为 TRUE如果最后的 FETCH 返回一行,则判定为 FALSE%FOUND如果最后的 FETCH 返回一行,则判定为 TRUE如果因为没有多行而使最后的 FETCH 失败,则判定为 FALSE,78,显式游标的属性(续),%ROWCOUNT返回当前从活动集合获取的行数%ISOPEN如果打开显示游标,则判定为 TRUE如果关闭显示游标,则判定为 FALSE,79,显式游标的属性(续),示例IF emp_cur%ISOPEN THENFETCH emp_cur INTO m_rec;IF emp_cur%FOUND THENmsr_no:=emp_cur%ROWCOUNT;END IF;ELSEOPEN emp_cur;END IF;,80,游标 FOR 循环,将它的循环索引声明为%ROWTYPE 的记录隐式地打开游标从活动集反复获取行的值并传送到记录中的字段在处理完所有行,并且循环退出时,隐式地关闭游标,81,游标 FOR 循环(续),为满足与游标名相关的查询的每一行执行循环结构中的语句游标 FOR 循环用于简化代码编写,82,游标 FOR 循环(续),DECLARECURSOR emp_cur ISSELECT empno,ename,job,sal FROM emp;BEGINFOR mrec IN emp_curLOOPINSERT INTO tempVALUES(mrec.empno,mrec.ename,mrec.job,mrec.sal);END LOOP;END;,83,参数化的游标,游标也可接收参数这些参数仅可用于游标的 SELECT 语句的输入游标参数可以在查询中常量出现的任何位置上出现可以在 OPEN 语句或游标 FOR 循环中提供参数值,84,参数化的游标(续),DECLARECURSOR emp_cur ISSELECT empno,ename,job,sal FROM empWHERE job=pjob;mjob emp.job%TYPEBEGINmjob:=,85,游标 FOR UPDATE OF 和 CURRENT OF,CURRENT OF 子句用于在 UPDATE 或 DELETE 语句中以引用游标当前行必须使用 FOR UPDATE OF 子句声明游标,并在一行上打开并定位如果游标没有打开,则 CURRENT OF 子句将产生错误,86,游标 FOR UPDATE OF 和 CURRENT OF(续),如果游标已经打开,但没有处理 FETCH 或最后一个 FETCH 没有返回任何行,则将产生预定义例外 NO_DATA_FOUND,87,游标 FOR UPDATE OF 和 CURRENT OF(续),DECLARECURSOR emp_cur ISSELECT empno,ename,job,sal FROM empWHERE job=pjob FOR UPDATE OF sal;BEGINFOR mrec IN emp_cur LOOPUPDATE emp SET sal=sal*0.15WHERE CURRENT OF emp_cur;END LOOP;END;,88,隐式游标的属性,虽然 OPEN、CLOSE 和 FETCH 语句不能用于操作 SQL%游标,但属性可以用于访问游标的环境区域在游标自动打开之前,属性判定为 NULL,89,隐式游标的属性(续),下列四个游标属性可以用于访问 SQL%游标的环境区域SQL%NOTFOUNDSQL%FOUNDSQL%ROWCOUNTSQL%ISOPEN,90,隐式游标的属性(续),SQL%NOTFOUND如果 INSERT、UPDATE 或 DELETE 语句没有影响行,则判定为 TRUE,否则判定为 FALSESQL%FOUND逻辑上与 SQL%NOTFOUND 相反 如果 INSERT、UPDATE 或 DELETE 影响了一行或多行,则判定为 TRUE,否则判定为 FALSE,91,隐式游标的属性(续),SQL%ROWCOUNT返回 INSERT、UPDATE 或 DELETE 语句影响的行数SQL%ISOPENOracle 执行完与其关联的 SQL语句后,将自动关闭隐式游标 对于隐式游标,总是将 SQL%ISOPEN 判定为 FALSE,92,隐式游标的属性(续),示例DELETE FROM emp WHERE empno=7864;IF SQL%NOTFOUND THEN.END IF;,93,PL/SQL 表,TABLE 类型的对象称为 PL/SQL 表可以将其可视化为单维的、具有无限多个元素的垂直数组表大小不受限制,即添加新行时它的大小将增加PL./SQL 表使用主键,对行进行类似于数组那样的访问,94,PL/SQL 表(续),PL/SQL 表的声明分为两个步骤 定义一个 TABLE 类型 TYPE IS TABLE OF列类型|变量数据类型 NOT NULLINDEX BY BINARY_INTEGER;声明该类型的 PL/SQL 表;,95,PL/SQL 表(续),示例TYPE name_tab_typ IS TABLE OF CHAR(15)INDEX BY BINARY_INTEGER;name_table name_tab_typ;,96,PL/SQL 表(续),可以通过使用具有类似于数组语法的主键值来引用行(I)其中 I 是索引下标 示例name_table(3),97,PL/SQL 表(续),还可以将 PL/SQL 表达式的值赋予给特定行(I):=plsql_expression;示例name_table(5):=MICKY;,98,PL/SQL 记录,类型为 RECORD 的对象称为 PL/SQL 记录PL/SQL 记录具有唯一命名的字段,这些字段可以属于不同的数据类型,99,PL/SQL 记录(续),通过两个步骤对 PL/SQL 记录进行了声明 定义一个 RECORD 类型 TYPE IS RECORD(fieldname1 NOT NULL:fieldnameN NOT NULL);(%TYPE 和%ROWTYPE 可用于指定 声明该类型的 PL/SQL记录;,100,PL/SQL 记录(续),只有对字段进行了初始化后才可以添加 NOT NULL 约束示例TYPE route_rec_type IS RECORD(route_code VARCHAR2(7)NOT NULL:=SAN-LOU,first_fare fare.first_fare%TYPE,eco_fare fare.eco_fare%TYPE);route_rec route_rec_type;,101,PL/SQL 记录(续),可以在声明中初始化记录 示例 TYPE timetype IS RECORD(tsecond SMALLINT:=0,tminute SMALLINT:=0,thour SMALLINT:=0);声明了 timetype 类型的记录后,字段初始值为零,102,PL/SQL 记录(续),可以使用点号引用记录中的字段.示例route_rec.eco_fare,103,PL/SQL 记录(续),可以一次对所有字段赋值 通过将一个记录赋值给另一个具有相同类型的记录 route_rec1:=route_rec2;使用 SELECT INTO 或 FETCH INTO 语句 SELECT route_code,first_fare,eco_fare INTO route_rec1 FROM fareWHERE route_code=SAN-LOU;(列名称必须按照与记录中字段相同的顺序出现),104,PL/SQL 记录(续),一个记录可以是另一个记录的组件PL/SQL 允许声明并引用嵌套记录,105,PL/SQL 记录(续),示例TYPE timetype IS RECORD(tminute SMALLINT,thour SMALLINT);TYPE meetingtype IS RECORD(mday DATE,mtime timetype);meeting meetingtype;seminar meetingtype;,106,PL/SQL 记录(续),示例(续)TYPE partytype IS RECORD(pday DATE,ptime timetype);party partytype;,107,PL/SQL 记录(续),PL/SQL 允许嵌套记录赋值给另一个具有相同数据类型的记录 seminar.time:=meeting.time;如果所包括的记录属于不同的数据类型,也允许一个嵌套记录赋值给另一个记录 party.time:=meeting.time;,108,应用于Web的面向对象关系型数据库管理系统:Oracle,REF 游标、过程和函数,3,109,本章目标,游标类型和变量 子程序简介 子程序的优点 存储程序函数RETURN 语句 过程和函数的参数模式 查看存储子程序的错误 存储子程序的优点,110,游标类型和变量,PL/SQL 程序不能将游标作为参数传递到另一个程序PL/SQL 程序仅能打开游标并处理程序自身内的相应信息要解决功能限制,用程序可以声明两个不同的游标类型及相应的游标变量,111,游标类型和变量(续),根据游标的不同声明方式,游标可以是 强型弱型,112,游标类型和变量(续),强型游标 游标类型的声明包括为游标类型指定了形态或属性的 RETURN 子句 强型游标类型限制随后使用该类型的游标变量的定义示例TYPE emp_cur IS REF CURSOR RETURN emp.empno%TYPE;emp_cursor1 cur_emp;,113,游标类型和变量(续),弱型游标 程序可以使用弱型游标类型声明任何形态的游标变量 因为没有返回值,所以游标变量的形态是独立的 这增加了游标变量的灵活性,有利于进一步的更改 示例TYPE emp_cur IS REF CURSOR;,114,子程序,子程序退出时,声明部分的对象是本地的并且终止其存在 可以使用支持 PL/SQL 的任何 Oracle 工具进行定义 它们可以在 PL/SQL 程序块、过程、函数和数据包中声明,115,子程序的优点,具有可扩展性 可以自定义 PL/SQL 语言以满足应用程序的需要 提高可复用性和可维护性子程序只要有效,就完全可以用于任何数目的应用程序中简化了维护/优化过程,因为如果定义更改只有子程序受到影响,116,子程序的优点(续),具有模块化特性可以将程序拆分为可管理的、明确定义的逻辑块支持自顶向下的设计和逐步细化的解决问题的方法抽象内容帮助允许与细节在精神上分离这种截取方式允许程序员在主程序的测试并调试完成后再进行过程/函数的定义,117,存储过程,执行特定操作的子程序存储于数据库中并可由任意匿名块调用能够接受参数在参数声明中的数据类型区分符应为无限制的,118,存储过程(续),具有两个部分 说明以关键字 PROCEDURE 开始,以过程名或参数列表结束 主体以关键字 IS 开始,以关键字 END 结束,后面可以跟可选过程名称,119,存储过程(续),CREATE OR REPLACE PROCEDURE(参数1,参数N)IS局部声明BEGIN可执行语句;EXCEPTION 例外处理程序;END;参数代表 变量名 IN|OUT|IN OUT 数据类型:=|DEFAULT 值,120,存储过程(续),示例 CREATE PROCEDURE branch_sum(p_brnch branch.branch_code%TYPE)ISdeclare variables;BEGIN可执行语句;EXCEPTIONWHEN NO_DATA_FOUND THEN语句;END branch_sum;,121,存储过程(续),创建过程时,Oracle 自动执行下列步骤 编译过程存储所编译的代码在数据库中存储过程PL/SQL 编译程序用于编译代码 如果发生错误,也可创建过程,但是无效,122,存储过程(续),可以使用 SHOW ERRORS 命令或下列命令查看编译错误 SELECT*FROM USER_ERRORS;Oracle 将编译过程装入 SGA 中 其他用户也可以执行存储在 SGA 中的相同过程,123,存储过程(续),Oracle 分三个步骤执行过程验证用户访问如果为非法用户,则拒绝访问验证过程有效性如果为非法过程,则不执行执行过程可以通过下列方式检查过程的有效性 SELECT OBJECT_NAME,OBJECT_TYPE,STATUSFROM USER_OBJECTSWHERE OBJECT_TYPE=PROCEDURE;,124,存储过程的优点,增强了数据安全性 可以授权用户访问能执行表的存储过程,但不授权他们访问表自身提高了数据库性能 通过网络发送的信息有所减少 编译不需要执行代码 过程存在于共享池中,所以不需要进行磁盘检索,125,存储过程的优点(续),节省内存 只需要在内存中装入过程的一个拷贝便可供多个用户执行 提高了开发的工作效率 通过编写单一的过程可以避免冗余程序代码,并且提高了生产效率 完整性 只需要测试一次,以保证它能够返回正确的结果,126,调用存储过程,可以作为 PL/SQL 语句调用过程 示例branch_sum(NYK);可以从 SQL*Plus 中调用单独的过程 示例SQL EXECUTE branch_sum(NYK);,127,维护存储过程,可以使用 DROP 命令删除过程 DROP PROCEDURE;示例DROP PROCEDURE branch_sum;,128,函数,返回值的子程序 具有一个 RETURN 子句 存储于数据库中并可由任意匿名程序块调用 通常可以接受参数 在参数声明中的数据类型区分符应为无限制的,129,函数(续),具有两个部分 说明以关键字 FUNCTION 开始,以 RETURN 子句结束 主体以关键字 IS 开始,以关键字 END 结束,后面可以跟可选函数名称,130,函数(续),CREATE OR REPLACE FUNCTION(参数1,参数N)RETURN datatype IS局部声明BEGIN可执行语句;EXCEPTION例外处理程序END;参数代表的是变量名 IN|OUT|IN OUT 数据类型:=|DEFAULT 值,131,函数(续),示例 CREATE FUNCTION day_fn(mday NUMBER)RETURN CHAR ISdisp_day CHAR(15);BEGIN可执行语句;RETURN disp_day;EXCEPTION 语句;END day_fn;,132,调用函数,作为 PL/SQL 语句调用函数 示例chardays:=day_fn(3);作为表达式的一部分调用函数 示例IF day_fn(3)=TUESDAY THEN语句;END IF;,133,维护函数,可以使用 DROP 命令删除函数 DROP FUNCTION;示例DROP FUNCTION day_fn;,134,RETURN 语句,立即完成子程序的执行,并将控制返回给调用者 内置过程 不可以包含表达式 在实现过程的正常结束之前将控制返回给调用者 内置函数 必须包含表达式,并在执行时判定,135,过程和函数的参数模式,用于定义正式参数的行为 可以与其他子程序一起使用 三个参数模式 IN(默认)OUTIN OUT避免在函数中使用 OUT 和 IN OUT 模型,136,过程和函数的参数模式(续),IN允许将值传送到被调用的子程序 在子程序内部,它的作用如同常数 实际对应参数可以是一个常数、数据量、初始化变量或表达式 可以被初始化为默认值,137,过程和函数的参数模式(续),OUT允许值返回到子程序的调用者 在子程序的内部,它的作用如同未初始化的变量 实际的对应参数应为一个变量;不能为一个常量或一个表达式 其值不能对另一个变量赋值,也不能对其自身再次赋值,138,过程和函数的参数模式(续),IN OUT允许传送初始值,并将更新的值返回给调用者 在子程序内部,它的作用如同未初始化的变量 实际的对应参数应为一个变量;不能为一个常量或一个表达式 它可以被赋值,它的值也可以对另一个变量赋值,139,调试存储子程序,可以使用 DBMS_OUTPUT 提供的数据包调试存储子程序 可以使用 PUT 和 PUT_LINE 语句将变量和表达式的值输出到显示器 还可以使用 SHOW ERRORS 命令查看编译错误 SHOW ERRORS PROCEDURE|FUNCTION|PACKAGE;,140,存储子程序的优点,更高的工作效率 通过采用存储子程序的库设计应用程序,可以避免冗余编码,从而提高工作效率 更佳的性能 通过使用子程序可以减少从到 Oracle的调用,因此提高了应用程序的性能,141,存储子程序的优点(续),节省内存 只需要将子程序的一个拷贝装入到内存中就可以供多个用户执行,这样应用程序就可以需要更少的内存 应用程序完整性 通过采用存储子程序的库来开发所有应用程序,降低了编码错误的可能性,142,存储子程序的优点(续),更加严密的安全性 存储子程序可以帮助加强数据安全 DBA 通过仅授权访问子程序来限制用户进行特定数据库操作,143,应用于Web的面向对象关系型数据库管理系统:Oracle,使用数据包和数据库触发器,4,144,本章目标,数据包 数据包的优点 数据包说明 数据包主体 使用游标变量 数据库触发器简介,145,本章目标(续),创建数据库触发器 INSTEAD OF 触发器 触发器的限制 启用/禁用触发器 放置触发器 编译和调试触发器,146,数据包,将逻辑相关的 PL/SQL 类型、对象和子程序进行分组的数据库对象 不能对它们进行调用,也不能对其传送参数或嵌套 这里有两个部分 说明主体,147,数据包的优点,模块化特性允许您将相关的类型、对象和子程序封装入一个命名的 PL/SQL 模块具有简单、清晰、定义明确的接口,便于理解 可以协助应用程序开发,148,数据包的优点(