⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 第一章 pl-sql一览 - pl-sql用户指南与参考 - whatiswhat.htm

📁 sql初学者不错的教程
💻 HTM
📖 第 1 页 / 共 5 页
字号:
                        <UL>
                          <LI>集合 </LI></UL>
                        <P>集合类型TABLE和VARRAY可以让我们声明索引表、嵌套表和变长数组(略称varray)。集合是类型相同的元素有序组合。在集合中,每个元素都有唯一一个能够确定该元素在集合中位置的下标索引。下面是嵌套表的一个例子: 
                        </P>
                        <BLOCKQUOTE>
                          <TABLE>
                            <TBODY>
                            <TR>
                              <TD 
                                noWrap><STRONG>DECLARE</STRONG><BR>&nbsp;&nbsp;<STRONG>TYPE</STRONG>&nbsp;staff&nbsp;<STRONG>IS</STRONG>&nbsp;<STRONG>TABLE</STRONG>&nbsp;<STRONG>OF</STRONG>&nbsp;employee;<BR><BR>&nbsp;&nbsp;staffer&nbsp;&nbsp;&nbsp;employee;<BR><BR>&nbsp;&nbsp;<STRONG>FUNCTION</STRONG>&nbsp;new_hires(hiredate&nbsp;<STRONG>DATE</STRONG>)<BR>&nbsp;&nbsp;&nbsp;&nbsp;<STRONG>RETURN</STRONG>&nbsp;staff&nbsp;<STRONG>IS</STRONG><BR>&nbsp;&nbsp;<STRONG>BEGIN</STRONG><BR>&nbsp;&nbsp;&nbsp;&nbsp;...<BR>&nbsp;&nbsp;<STRONG>END</STRONG>;<BR><STRONG>BEGIN</STRONG><BR>&nbsp;&nbsp;staffer&nbsp;&nbsp;&nbsp;&nbsp;:=&nbsp;new_hires(<EM>'10-NOV-98'</EM>)(5);<BR>&nbsp;&nbsp;...<BR><STRONG>END</STRONG>; 
                              </TD></TR></TBODY></TABLE></BLOCKQUOTE>
                        <P>集合有些像三代语言中的数组,并且可以作为参数进行传递。 </P>
                        <UL>
                          <LI>记录 </LI></UL>
                        <P>我们知道,可以使用%ROWTYPE属性获取数据表中一行的记录类型,其实我们还可以定义自己的记录类型。 
                        </P>
                        <P>记录包含名称不可重复的域,域可以有不同的数据类型。假设我们设计了一个雇员记录类型,其中有名字、工资和雇用日期,这些项虽然类型不同,但逻辑上都是相关联的。看一下下面的例子: 
                        </P>
                        <BLOCKQUOTE>
                          <TABLE>
                            <TBODY>
                            <TR>
                              <TD 
                                noWrap><STRONG>TYPE</STRONG>&nbsp;timerec&nbsp;<STRONG>IS</STRONG>&nbsp;<STRONG>RECORD</STRONG>(<BR>&nbsp;&nbsp;hours&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<STRONG>SMALLINT</STRONG>,<BR>&nbsp;&nbsp;minutes&nbsp;&nbsp;&nbsp;<STRONG>SMALLINT</STRONG><BR>);<BR><BR><STRONG>TYPE</STRONG>&nbsp;meetingtyp&nbsp;<STRONG>IS</STRONG>&nbsp;<STRONG>RECORD</STRONG>(<BR>&nbsp;&nbsp;date_held&nbsp;&nbsp;&nbsp;<STRONG>DATE</STRONG>,<BR>&nbsp;&nbsp;DURATION&nbsp;&nbsp;&nbsp;&nbsp;timerec,&nbsp;&nbsp;&nbsp;<EM>--&nbsp;nested&nbsp;record</EM><BR>&nbsp;&nbsp;LOCATION&nbsp;&nbsp;&nbsp;&nbsp;<STRONG>VARCHAR2</STRONG>(20),<BR>&nbsp;&nbsp;purpose&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<STRONG>VARCHAR2</STRONG>(50)<BR>); 
                              </TD></TR></TBODY></TABLE></BLOCKQUOTE>
                        <P>这里要注意的是,记录里可以嵌套记录类型。也就是说,记录本身也可以作为另一个记录的组成部分。 </P>
                        <UL>
                          <LI>对象类型 </LI></UL>
                        <P>PL/SQL中的面向对象编程是基于对象类型的。对象类型把数据和用于数据操作的函数和过程封装起来。其中,对象类型中的变量称为属性,函数和过程称为方法。对象类型是把大系统划分成多个逻辑实体来降低问题的复杂度,这就能使我们创建模块化、可维护和重用性好的组件了。我们在用CREATE 
                        TABLE定义对象类型的时候,常常是创建一个对真实世界对象的抽象的模板。如下面的银行账户例子中显示,模板只指定了应用程序的环境中会使用到的属性和方法: 
                        </P>
                        <BLOCKQUOTE>
                          <TABLE>
                            <TBODY>
                            <TR>
                              <TD 
                                noWrap><STRONG>CREATE</STRONG>&nbsp;<STRONG>TYPE</STRONG>&nbsp;bank_account&nbsp;<STRONG>AS</STRONG>&nbsp;OBJECT(<BR>&nbsp;&nbsp;acct_number&nbsp;&nbsp;&nbsp;<STRONG>INTEGER</STRONG>(5),<BR>&nbsp;&nbsp;balance&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<STRONG>REAL</STRONG>,<BR>&nbsp;&nbsp;status&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<STRONG>VARCHAR2</STRONG>(10),<BR>&nbsp;&nbsp;MEMBER&nbsp;<STRONG>PROCEDURE</STRONG>&nbsp;<STRONG>OPEN</STRONG>(amount&nbsp;<STRONG>IN</STRONG>&nbsp;<STRONG>REAL</STRONG>),<BR>&nbsp;&nbsp;MEMBER&nbsp;<STRONG>PROCEDURE</STRONG>&nbsp;verify_acct(num&nbsp;<STRONG>IN</STRONG>&nbsp;<STRONG>INTEGER</STRONG>),<BR>&nbsp;&nbsp;MEMBER&nbsp;<STRONG>PROCEDURE</STRONG>&nbsp;<STRONG>CLOSE</STRONG>(num&nbsp;<STRONG>IN</STRONG>&nbsp;<STRONG>INTEGER</STRONG>,&nbsp;amount&nbsp;<STRONG>OUT</STRONG>&nbsp;<STRONG>REAL</STRONG>),<BR>&nbsp;&nbsp;MEMBER&nbsp;<STRONG>PROCEDURE</STRONG>&nbsp;deposit(num&nbsp;<STRONG>IN</STRONG>&nbsp;<STRONG>INTEGER</STRONG>,&nbsp;amount&nbsp;<STRONG>IN</STRONG>&nbsp;<STRONG>REAL</STRONG>),<BR>&nbsp;&nbsp;MEMBER&nbsp;<STRONG>PROCEDURE</STRONG>&nbsp;withdraw(num&nbsp;<STRONG>IN</STRONG>&nbsp;<STRONG>INTEGER</STRONG>,&nbsp;amount&nbsp;<STRONG>IN</STRONG>&nbsp;<STRONG>REAL</STRONG>),<BR>&nbsp;&nbsp;MEMBER&nbsp;<STRONG>FUNCTION</STRONG>&nbsp;curr_bal(num&nbsp;<STRONG>IN</STRONG>&nbsp;<STRONG>INTEGER</STRONG>)<BR>&nbsp;&nbsp;&nbsp;&nbsp;<STRONG>RETURN</STRONG>&nbsp;<STRONG>REAL</STRONG><BR>); 
                              </TD></TR></TBODY></TABLE></BLOCKQUOTE>
                        <P>运行时,当数据结构被赋值之后,我们就可以创建抽象的银行账户了。我们可以按照需求创建任意个实例(称为对象)。每个对象都有账号,余额和状态。 
                        </P>
                        <P class=title2>10、信息隐藏</P>
                        <P>有了信息隐藏,我们就可以只关心给定的设计级别的算法和数据结构设计。信息隐藏能把高阶的设计决定从频繁改变的低阶设计细节分离出来。 
                        </P>
                        <UL>
                          <LI>算法 </LI></UL>
                        <P>我们可以通过自顶而下(top-down)的设计来实现算法隐藏。一旦我们明确了低阶过程的实现目的并定义好相应的接口说明,就可以忽略实现细节部分。例如,我们只需要知道将一个雇员的工资金额传递给过程raise_salary就可以提高该雇员的工资。任何对raise_salary方法的变动,对于应用程序来说,都是透明的。 
                        </P>
                        <UL>
                          <LI>数据结构 </LI></UL>
                        <P>我们可以通过数据封装来实现信息隐藏。开发一组操作数据结构的工具子程序,就可以让使用它的用户和开发人员分离。这样一来,开发人员只需了解如何使用这些子程序来操作数据,并不需要知道数据真正的含义。 
                        </P>
                        <P>使用PL/SQL包,我们就可以指定哪些子程序是公有哪些是私有,更好的提供封装,简化维护。 </P>
                        <P class=title2>11、错误控制</P>
                        <P>PL/SQL能够轻松的发现并处理预定义和用户定义的错误条件(即异常)。错误发生时,异常就会被抛出。也就是说,正常的执行会终止,程序控制权将交给PL/SQL块或子程序的异常处理部分。为控制被抛出的异常,我们需要单独编写异常控制句柄(即异常控制程序)。 
                        </P>
                        <P>预定义异常会被系统隐式地抛出,例如,用一个数字除以零,PL/SQL就会自动抛出预定义异常ZERO_DIVIDE。对于用户自定义异常,必须由我们显式地使用RAISE语句抛出。 
                        </P>
                        <P>我们可以在任何PL/SQL块或子程序的声明部分定义自己的异常。在执行部分,我们检查那些需要特别对待的条件,如果错误条件满足,就可以使用 
                        RAISE抛出异常。在下面的例子中,我们要计算售货员的奖金。奖金的多少取决于他的工资(salary)和佣金(commission)。所以,如果佣金为空的话,我们就要抛出异常comm_missing。 
                        </P>
                        <BLOCKQUOTE>
                          <TABLE>
                            <TBODY>
                            <TR>
                              <TD 
                                noWrap><STRONG>DECLARE</STRONG><BR>&nbsp;&nbsp;...<BR>&nbsp;&nbsp;comm_missing&nbsp;&nbsp;&nbsp;<STRONG>EXCEPTION</STRONG>;&nbsp;&nbsp;&nbsp;<EM>--&nbsp;declare&nbsp;exception</EM><BR><STRONG>BEGIN</STRONG><BR>&nbsp;&nbsp;...<BR>&nbsp;&nbsp;<STRONG>IF</STRONG>&nbsp;commission&nbsp;<STRONG>IS</STRONG>&nbsp;<STRONG>NULL</STRONG>&nbsp;<STRONG>THEN</STRONG><BR>&nbsp;&nbsp;&nbsp;&nbsp;<STRONG>RAISE</STRONG>&nbsp;comm_missing;&nbsp;&nbsp;&nbsp;<EM>--&nbsp;raise&nbsp;exception</EM><BR>&nbsp;&nbsp;<STRONG>END</STRONG>&nbsp;<STRONG>IF</STRONG>;<BR><BR>&nbsp;&nbsp;bonus&nbsp;&nbsp;&nbsp;&nbsp;:=&nbsp;(salary&nbsp;*&nbsp;0.10)&nbsp;+(commission&nbsp;*&nbsp;0.15);<BR><STRONG>EXCEPTION</STRONG><BR>&nbsp;&nbsp;<STRONG>WHEN</STRONG>&nbsp;comm_missing&nbsp;<STRONG>THEN</STRONG>&nbsp;&nbsp;&nbsp;<EM>--&nbsp;process&nbsp;the&nbsp;exception</EM><BR>&nbsp;&nbsp;&nbsp;&nbsp;...<BR><STRONG>END</STRONG>; 
                              </TD></TR></TBODY></TABLE></BLOCKQUOTE>
                        <P class=title1>二、PL/SQL架构</P>
                        <P>PL/SQL的编码和运行时系统是一项技术,而不是一个独立的产品。可以把这项技术想象成一个能够编译并运行PL/SQL块和子程序的引擎。这个引擎可以安装在Oracle服务器上或安装在Oracle 
                        Forms,Oracle Reports这样的开发工具中。所以,PL/SQL可以在两种环境中存在: </P>
                        <OL>
                          <LI>Oracle数据库服务器 
                          <LI>Oracle开发工具 </LI></OL>
                        <P>这两种环境是独立的。PL/SQL虽被绑定到Oracle服务器上,但在某些工具中是无法使用的。在这两种环境下,PL/SQL引擎都能接受有效的 
                        PL/SQL块或子程序。下图是PL/SQL引擎处理匿名块的过程,引擎会处理过程化语句,而把SQL语句发送给Oracle服务器端的SQL语句执行程序(SQL 
                        Statement Executor)来处理。 </P><IMG alt="" 
                        src="第一章 PL-SQL一览 - PL-SQL用户指南与参考 - whatiswhat.files/o_1-4.gif" 
                        name=""> 
                        <P class=title2>1、Oracle数据库中</P>
                        <P>缺乏本地PL/SQL引擎的应用开发工具就必须依赖于Oracle来处理PL/SQL块和子程序。Oracle服务器除了能够处理SQL语句外,还会处理PL/SQL块和子程序,它会将块与子程序传给它本地的PL/SQL引擎。 
                        </P>
                        <UL>
                          <LI>匿名块 </LI></UL>
                        <P>匿名PL/SQL块能被嵌到Oracle预编译程序(Oracle 
                        Precompiler)或是OCI程序中。运行的时候,不含PL/SQL引擎的程序会把这些块发送到Oracle服务器编译并执行。 
                        </P>
                        <UL>
                          <LI>存储过程 </LI></UL>
                        <P>子程序可以独立编译并存储在Oracle数据库。使用CREATE语句显式创建的子程序就是一个"存储"子程序。一旦编译并保存到数据词典中,它就成了一个模式对象(schema 
                        object),可以被许多连到数据库的应用程序调用。 </P>
                        <P>定义在包内的存储子程序称为打包子程序(packaged 
                        subprogram);单独定义的存储子程序称为独立子程序(standalone 
                        subprogram);而在另外一个子程序或PL/SQL块内定义的存储子程序称为本地子程序,这样的子程序不能被其他应用程序调用,只供本地使用。 
                        </P>
                        <P>存储过程执行效率高,耗内存少,应用集成,安全性好。例如,我们设计出一套存储过程和函数时,应用程序就可以调用这些函数和方法,这样就能避免大量的冗余代码提高效能。 
                        </P>
                        <P>我们可以从数据库触发器、其他存储子程序、Oracle预编译程序、OCI程序或是SQL*Plus等,调用存储子程序。例如,我们可以像下面这样从SQL*Plus中调用独立子程序create_dept: 
                        </P>
                        <BLOCKQUOTE>
                          <TABLE>
                            <TBODY>
                            <TR>
                              <TD 
                                noWrap><STRONG>SQL</STRONG>&gt;&nbsp;CALL&nbsp;create_dept(<EM>'FINANCE'</EM>,&nbsp;<EM>'NEW&nbsp;YORK'</EM>); 
                              </TD></TR></TBODY></TABLE></BLOCKQUOTE>
                        <P>子程序以分析、编译过的形式保存在数据库中。所以,在被调用时,它们会被立即加载并传递到PL/SQL引擎。并且,它们还会利用共享内存,这样,每次只要有一个子程序需要被加载到内存,就能被多个用户调用执行。 
                        </P>
                        <UL>
                          <LI>数据库触发器 </LI></UL>
                        <P>数据库触发器是与数据库中某个数据表、视图或事件相关联的存储子程序。举一个例子,我们可以让Oracle数据库在INSERT、UPDATE或 
                        DELETE表达式影响一个表之前或之后来自动激活一个触发器。触发器的用途之一就是审核数据修改。例如,下面的表级(table-level)触发器会在emp表的salaries字段更新后被激活。 
                        </P>
                        <BLOCKQUOTE>
                          <TABLE>
                            <TBODY>
                            <TR>
                              <TD 
                                noWrap><STRONG>CREATE</STRONG>&nbsp;<STRONG>TRIGGER</STRONG>&nbsp;audit_sal<BR>&nbsp;&nbsp;AFTER&nbsp;<STRONG>UPDATE</STRONG>&nbsp;<STRONG>OF</STRONG>&nbsp;sal<BR>&nbsp;&nbsp;<STRONG>ON</STRONG>&nbsp;emp<BR>&nbsp;&nbsp;<STRONG>FOR</STRONG>&nbsp;EACH&nbsp;<STRONG>ROW</STRONG><BR><STRONG>BEGIN</STRONG><BR>&nbsp;&nbsp;<STRONG>INSERT</STRONG>&nbsp;<STRONG>INTO</STRONG>&nbsp;emp_audit<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<STRONG>VALUES</STRONG>&nbsp;...<BR><STRONG>END</STRONG>; 
                              </TD></TR></TBODY></TABLE></BLOCKQUOTE>
                        <P>触发器执行部分可以包括过程语句和SQL数据操作语句。除了表级触发器以外,还包含替代触发器(instead-of 
                        triggers for views)和系统触发器(system-event trigger)。 </P>
                        <P class=title2>2、Oracle工具中</P>
                        <P>在包含PL/SQL引擎的条件下,应用开发工具就能够处理PL/SQL块和子程序。开发工具会把块传给它的本地PL/SQL引擎。引擎会在应用程序段执行所有的过程语句,只把SQL语句发送给Oracle。因此,大多部分工作会在应用程序端完成,而不是在服务器端。进一步说,如果块中不包含任何 
                        SQL语句的话,这个引擎会在应用程序端执行全部的代码。 </P>
                        <P class=title1>三、PL/SQL的优势</

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -