(interbase之九)intebase的存储过程、触发器以及事件、异常
原创 kylixyqh
-------------------------------------------------------------------
说明:本来我想把《interbase中文开发指南》中有关存储过程、触发器的章节全部照搬过来,但考虑到存储过程、触发器的重要性,相信大部分人已经进行了相当的研究,因此,为了节约篇幅和时间,我把其中的定义、变量声明、语句语法等大量内容全部删除;其中,事务处理请参照前面的帖子。请大家谅解。感兴趣的可以参考有关资料。
一、使用存储过程、触发器的好处
1、在不需要客户端的情况下在服务器端执行复杂的操作
2、可以被多个客户端共享使用(代码共享)
3、极大的减小网络流量,提高网络利用率
4、在服务器端执行,速度快
5、可以将复杂的任务划分为多个简单的商业逻辑
6、存储过程对某些需要周期性处理的任务特别有用
7、存储过程在客户端和服务器端提供了良好的并发性
8、触发器是维护数据一致性的基本工具
9、触发器常被用在为插入新行提供唯一主键值
10、触发器常被用来保存一些状态信息
11、存储过程和触发器是interbase事件警告机理的有力组成部分
12、存储过程增强了数据的安全性
二、何时使用存储过程和触发器
存储过程:1、不需要任何客户端信息而在服务器端完成的操作2、涉及到大量行的操作、运算3、频繁的、周期性的操作4、那些被多个模块共同执行的操作
触发器:1、before insert/update触发器可以检查操作是否完成以及数据的一致性,或者为那些需要唯一编号的列提供数值2、before delete触发器可以在删除时检查主要明细表之间的关系,也可以终止删除。3、所有的before触发器均可以通过激发异常终止操作回退事务4、所有的after触发器均可以在更改完成后做一些审计或更改其他相关表的操作。
三、存储过程
一般的,interbase的存储过程分为两大类,它是根据客户端在调用存储过程时使用的不同方法划分的。一类是选择式存储过程,客户端使用select语句调用存储过程,此时存储过程的作用好像和表、视图一样,选择式存储过程必须返回一个或多个数值(在客户端的行为象数据行)或错误或参数信息。另一类是执行式存储过程,客户端使用excute procedure来调用存储过程,这类存储过程大多数只执行一些动作而不返回数值,当然它也可以返回一些参数信息。创建存储过程时你一定要事先规划好你准备按照哪一类进行编写,这是确保存储过程可能正确执行的良好习惯。如果你准备将来在客户端使用select调用,就遵守选择式存储过程的规则编写;如果你想使用excute procedure调用,就按照执行式存储过程的规则编写。存储过程的类型不同,suspend,exit,end的功能也不同。下面说明suspend,exit,end在两类存储过程中的作用。
1、suspend语句:在选择式存储过程中,当存储过程向客户端返回数据时,suspend暂时停止存储过程的执行,即挂起存储过程,直到客户端获取了返回值为止,然后接着suspend之后的语句继续执行。suspend的作用就是当有数据要返回客户端时防止客户端未成功取得返回值而继续执行存储过程,从而有可能导致将存储过程执行结束退出。根据上述说明,就可以了解,当你在选择式存储过程中使用select或select into等语句向客户端返回数据(行)时,在上述语句之后一定要紧跟suspend语句。在复杂的存储过程中,不可能只有select性质的sql语句,可能还有insert,update,delete等可执行语句,这时就要明白,在选择式存储过程中,suspend语句之后的所有可执行语句都被执行,尽管此时已经没有值要返回给客户端,最后的end语句终止整个存储过程的执行。interbase不推荐在执行式存储过程中使用suspend。因为在执行式存储过程中,suspend语句之后的所有语句永远都不会被执行,程序将直接跳转到最后一个end语句,并返回参数,退出存储过程。所以如果你偶尔(或不得不)没有遵守interbase推荐的规则在执行式存储过程中使用了suspend而产生了意料不到的结果,你就要思考一下suspend的用法了。
2、exit语句:在选择式存储过程中,exit语句直接将程序执行跳转到最后一个end语句从而终止存储过程的执行。因此,在选择式存储过程中,使用exit语句最理想的情况是当需要在满足一定条件时提前结束存储过程的执行。在执行式存储过程中,exit也将程序执行跳转到最后一个ennd语句,表明存储过程的工作已经完成,同时如果有返回参数的话,将他们返回给客户端。
3、end语句:在选择式存储过程中,当执行到最后一个end语句时,结束存储过程的执行,将控制权返给客户端,并设置sqlcode为100。在执行式存储过程中,最后一个end语句也终止存储过程的执行,同时将输出参数返回给客户端(如果有的话)。
因此,可以将suspend,exit,end三个语句的作用简明地总结如下:suspend用于返回具有数据行性质的数值给客户端;exit用于提前结束程序的执行;end则用于真正终止存储过程并将输出参数返回给客户端。
三、存储过程、触发器中的事件、异常、错误处理
1、事件:interbase一个显著的特点就是可以在存储过程、触发器中通过使用事件来进行异步消息处理。相信有很多人已经感受到服务器端和客户端进行异步消息处理的迫切性了。interbase在存储过程、触发器中允许使用post_event来帮助我们解决上述问题。所谓事件,实际就是一个自定义的消息标识,用以实现服务器与客户端的异步通信。使用事件的方法是:在存储过程或触发器中用post_event("xxxxx")定义并向interbase的消息管理队列添加注册消息,这是服务器端。在客户端,首先注册相应的消息,然后当服务器端投寄了消息之后,客户端对该消息作出相应的反应。需要注意的是,如果服务器端发起了多个相同的消息,那么服务器只向客户端投寄一个消息而不是将所有这些消息全部投寄给客户端。如果你使用delphi的IBX编写客户端的话,就可以很方便地使用TIBevent组件进行消息处理。
2、异常:异常是interbase数据库的一个对象,它实际是一个经过命名的错误。但是一定要注意而且区分,异常决不是用来处理intebase数据库错误的(比如主键约束错误等),它只是用来实现所谓的商业逻辑的。比如你不允许用户删除当前活动订单中的库存项目就可以用户执行存储过程欲删除库存时激发一个异常,表明不能进行删除。可见,异常完全是一个商业逻辑行为。异常被激发后,整个存储过程或触发器将被终止,该存储过程或触发器所在的事务链将被回退,并向客户端返回定义的有关错误说明。
事件与异常的比较:事件发生后,不影响程序的执行,事件在需要服务器端通知客户端消息时非常重要,事件机理本身是多线程结构,无须客户端一直去检测等待;异常激发后,则终止程序执行,回退全部事务。
3、intebase错误处理:在interbase中,错误一般分为数据库错误和数据库引擎错误。而在存储过程中,一般使用when....do语句进行错误处理,和delphi的try...exception类似。when...do可以捕获并处理一下三类错误:异常(用户自定义逻辑错误)、数据库错误(SQL错误:通过变量sqlcode进行检测)、数据库引擎错误(interbase错误:通过变量GDScode检测)。
本文地址:http://com.8s8s.com/it/it21340.htm