引言
PL/SQL的高级应用包括对存储过程、函数、包、触发器等的应用。
存储过程
在PL/SQL程序中,除匿名块以外,还有一类被命名的PL/SQL程序块,称为存储子程序。存储子程序以编译的形式存储在数据库服务器中,可以在应用程序中进行多次调用,是PL/SQL程序模块化的一种体现。PL/SQL存储子程序包括存储过程和(存储)函数两种。存储过程用于执行特定的操作,不需要返回值;函数用于返回特定的数据。在调用时,存储过程可以作为一个独立的表达式被调用,而函数只能作为表达式的一个组成部分被调用。
存储过程和函数具有一下特点:
- 存储过程和函数只在创建时需要编译,以后每次执行都不需要重新编译,而一般的SQL语句每次执行一次就会编译一次,因此使用存储过程和函数可提高数据库执行的速度。
- 通常,复杂的业务逻辑需要多条SQL语句,这些语句要分别从客户机发送到服务器,当客户机和服务器之间的操作很多时,将产生大量的网络传输。如果将这些操作放在一个函数或存储过程中,客户机和服务器之间的网络传输将会大大减少,可以降低网络的负载。
- 安全性高,存储过程和函数可以屏蔽对底层数据库对象的直接访问,无须拥有访问底层数据库对象的显示权限。
- 存储过程和函数创建一次可以多次使用,可以减少开发人员的工作量。
同时,存储过程和函数也具有以下缺点:
- 不可移植性:每种数据库内部编程语法都大不相同,当系统需要兼容多种数据库时,最好不要用存储过程和函数。
- 业务逻辑多次存在:采用存储过程和函数就意味着系统有一些业务逻辑不是在应用程序里处理,这种架构会增加一些系统维护和调试的成本。
- 可扩展性低:如果存储过程和函数中存在复杂运算,则会增加一些数据库服务端的处理成本,对于集中式数据库可能会导致系统的扩展性的问题。
- 引用对象的结构变更对高并发数据库性能影响较大。为了提升性能,数据库会将存储过程和函数代码编译成中间运行代码(类似于Java的class文件),所以其更像静态语言,当存储过程和函数(如表和视图等)结构改变后,存储过程或函数需要重新编译才能生效,对于一些高并发应用场景,在线变更结构的瞬间同事编译存储过程和函数,可能会导致数据库压力瞬间上升而引起故障。
函数
函数又称为存储函数、存储结构,用户定义的函数可以被SQL语句或PL/SQL程序直接调用。函数与存储过程的不同之处在于函数有一个显式返回值,而存储过程只能依靠OUT或IN OUT返回数据。
包
在PL/SQL程序开发中,为了方便实现模块化程序的管理,可以将PL/SQL元素(如存储过程、函数、变量、常量、自定义数据类型、游标等)根据模块所需的程序结构组织在一起,存放在一个包中,成为一个完整的单元,并在编译之后存储在数据库服务器中,作为一种全局结构,供应用程序调用。 在Oracle数据库中,包有两类,一类是系统内置的包,每个包实现特定的应用过程、函数、常量等的集合,如DBMS_OUTPUT.put_line()就是调用了DBMS_OUTPUT包中的put_line()函数;另一类是根据应用需要由用户创建的包。
触发器
触发器是一种特殊类型的存储过程,其基本定义形式与存储过程和函数类似,唯一不同的就是所有的存储过程和函数均需用户显示调用,而触发器是当某个特定事件发生时,由系统自动调用执行,不能接收参数,即触发器是自动隐式运行的。特定事件通常是指对数据库对象的某个操作,如对数据库表进行的DML操作或对视图进行的类似操作,同时Oracle还将触发器的功能扩展到对如数据库的启动与关闭等事件的触发,所以触发器常用来完成数据库完整性约束难以完成的复杂业务规则的约束,或监视对数据库的各种操作。
- 触发器的组成
- 触发事件:引起触发器被触发的事件,如DML语句、DDL语句、数据库系统事件(如系统启动或退出及异常错误等)、用户事件(如登录或退出数据库)等。
- 触发时间:指该触发器是在触发事件发生前(BEFFORE)还是之后(AFTER)触发,也就是触发事件和该触发器的操作顺序。
- 触发操作:即触发器被触发之后执行的PL/SQL块。
- 触发对象:包括表、视图、模式、数据库。这有这些对象上发生了符合条件的触发事件时,才会执行触发操作。
- 触发条件:由WHEN子句指定的一个逻辑表达式子。只有当该表达式的值为TURE时,遇到触发事件才会自动执行触发操作。
- 触发频率:说明触发器内定义的动作被执行的次数,即语句级触发器和行级触发器。
- 编写触发器时的注意事项
- 触发器不接收任何参数,并且只能是在产生了某一触发事件之后才会自动调用。
- 一个数据表最多只能有12个触发器(语句级、行级、BEFRORE、AFTER和DML操作的组合);同一时间、同一事件、同一类型的触发器只能有一个,并且触发器之间不能有矛盾。
- 一个触发器最大为32KB,所以如果需要编写的代码较多,可以通过过程或函数调用完成。
- 默认情况下,触发器不能使用事务级处理操作。因为触发器是触发语句的一部分,触发语句被提交、回退时,触发器也被提交、回退。
- 一个表上的触发器越多,对在该表上的DML操作的性能影响就越大。
- 在触发器的执行部分只能使用DML语句,不能使用DDL语句。
- 在触发器主体中不能申明任何LONG和BLOB变量。
- 不同类型的触发器(如DML触发器、INSTEAD-OF触发器、系统触发器)的语法格式和作用有较大区别。
- 触发器的分类
- DML触发器:建立在基本表上的触发器,相应基本表的INSERT、UPDATE、DELETE操作。
- 替代触发器(INSTEAD-OF触发器):建立在视图上的触发器,响应视图上的INSERT、UPDATE、DELETE操作。
- 系统触发器:建立在数据库系统和模式对象上的触发器,响应模式对象的CREATE\ALTER、DROP、GRANT等DDL操作,以及响应数据库服务的打开、关闭、错误等系统事件,或监控用户的行为操作。
|