| 基于Oracle数据库存储过程与触发器的应用 |
一般城市规划管理信息系统数据库在逻辑上包括工作流数据库、内务管理数据库及业务数据库。其中工作流数据库主要存贮工作流运行过程的数据,记录流程的执行状态和时间。根据工作流定义数据和工作流实例数据,进行流程监控和工作流程的查询;内务管理数据库主要存贮部门、工作人员、角色及其权限管理的数据;业务数据库主要存贮系统所处理的业务数据,业务数据的定义由在元数据库中的属性元数据记录,其生成时间、质量方面的属性由实例数据记录。为了更有效地提高数据库的整体性能,提高系统的运行时间,用好存储过程与触发器就显得十分重要。存储过程实质上是一个代码模块,它执行某些操作并返回该程序是否成功执行的标志。触发器是一种特殊类型的存储过程,当使用UPDATE、INSERT或DELETE一种或多种数据修改操作时,它就会触发,触发器还可以用来查询表的操作,执行复杂的SQL语句来强制复杂的业务规则或要求,助于强制引用完整性,以便在添加、更新或删除表中的行时保留表之间已定义的关系。
触发器的功能可用于许多方面,笔者对某市规划信息管理系统如何利用数据库的存储过程与触发器来创建自动流水号及进行系统安全与审计作了一定探讨。
1 自动增加流水号的创建该规划信息管理系统采用Oracle9i数据库[1],数据表的关系非常复杂,各个数据表需要有唯一标识符,如果以几个字段合起来作联合主键时,联合主键在数据库表插入、更新和删除记录时效率较低,且作外键时还会使引用表字段过多,从而影响数据库的整体性能。因此一般每个表都用各自的流水号作为主键,由于流水号是数据记录的唯一标识,不会重复。如内务管理子系统中的受理案件表(表 1),表中就有项目序号、项目编号、剩余天数这3个字段要用到流水号。在这个表中,其项目序号是客户看不到的,仅作为系统内部用来检索的标志;项目编号,一般是由当年的年份后面扩充5位再加顺序号组成。由于每一年的顺序号都要从头开始,因此它可以由创建过程与触发器共同来完成,当然也可选择通过直接创建触发器来完成流水号的自动增加。
| 表 1 受理案件表 |
![]() |
| 点击放大 |
下面介绍直接用触发器来完成创建,其具体代码如下:
create or replace trigger acceptcaseb_trigger before insert on ghoauser.acceptcaseb for each row
--其中GHOAUSER为表所属的用户
--其中acceptcaseb_trigger为触发发器的名
declare
maxcount integer; --用来暂存表中的记录数
maxvalue integer; --用来暂存系统日期转换值
com_num integer; --暂存USERCODE最大值
begin
select count(*) into maxcount from ghoauser.acceptcaseb;
select to_number(to_char(sysdate, ’ yyyy ’))*100000 into maxvalue from dual;
if maxcount >0 then
select max(usercode) into com_num from ghoauser.acceptcaseb;
if maxvalue < com_num then
:new.usercode:=com_num+1;
else
:new.usercode:= maxvalue +1;
end if;
else
:new.usercode:= maxvalue +1;
end if;
end;
在剩余天数字段是用来提醒办公人员,他所办的这个案件还剩几天要办完,以促使这个案件在规定的办文时限内完成。因此,当系统日期改变了,剩余天数字段就必须自动减1,另外,若遇到节假日,星期六,星期日等,还应从中自动剔除。具体实现代码如下所示:
CREATE OR REPLACE PROCEDURE “ GHOAUSER”.“ACCEPTCASEB_RPO”
AS
Begin
/*触发器名称:ACCEPTCASEB_RPO */
/*触发器所在表名称:ACCEPTCASEB */
/*当前用户:GHOAUSER */
IF (To_Char(sysdate, ’dy’) NOT IN (’星期六’, ’星期日’) OR
To_Char(sysdate, ’ MMDD’)NOT IN / *去除一年当中星期六, 星期日*/
(’ 0101’, ’ 0102’, ’ 0103’, ’ 0104 ’, ’ 0105’, ’0106’, ’0107 ’, ’0108’))
/*去除一年当中法定新年假期,还可以在这里增加需要扣除的日期* /
THEN
update GHOAUSER.ACCEPTCASEB set remaintdays= remaindays-1
where REMAINDAYS>0;
END IF;
end;
--通过JOB完成功能,其中JOB2为序号
variable job2 number;
begin
--下列语句功能:每天24点时执行一次更新操作
dbms_job.submit(:job2, ACCEPTCASEB_RPO; ’, SYSDATE, ’ sysdate+24/24+1’);
end;
begin
dbms_job.run(:job2);
end;
--若要移去时,可以用以下语句来取消这个JOB了运行
begin
dbms_job.remove(:job2);
end;
2 用触发器实现数据的审计与安全城市规划管理信息系统中的每一项业务都由不同的用户角色来承担,每一项业务都涉及业务的申请、初审、复审、批准等一系列办文流程管理,并且每项任务间都有严格的逻辑关系,每项任务都有明确的工作内容和不同的权限,因此必须用触发器来保证在关键表上的任何插入、更新或者删除动作以及当前时间、用户名都会被记录到审计表(TEMP_Audit)中[2], 以便日后通过审查可以了解哪位用户曾经修改了那些数据以及这些数据在修改前的状态,提供哪位用户更改了他人记录之证据;或者使用触发器不允许操作人员在周末修改限定的表。如在表 2中规定了不允许非工作时间(或周末)修改数据库。
| 表 2 角色表 |
![]() |
| 点击放大 |
要完成这个功能,首先应建立审计表,然后创建以下触发器:
CREATE TABLE temp_audit (
Username varchar2(10),
operation varchar2(6),
oper_date date,
DATA varchar2(12)
);
CREATE OR REPLACE TRIGGER AUDIT_TRIGGER BEFORE INSERT
OR DELETE OR UPDATE ON GHOAUSER.ACCEPTCASEB
BEGIN
--
--在emp_audit里创建一行,反映对ROLEB表的操作
--在期六、日不允许修改ROLEB表
--
if(to_char(sysdate, ’ DY’) IN(’ SUN’,‘SAT’))
RAISE_APPLICATION_ERROR (-20600, ’不能在周末修改表ROLEB’);
end if;
IF (INSERTING) THEN
INSERT INTO Temp_audit VALUES (user, ’ I’, now(), NEW.PURVIEW);
ENDIF
IF (updating) THEN
INSERT INTO emp_audit values (user, ’ U’, now(), NEW.PURVIEW);
ENDIF;
IF(DELETING) THEN
INSERT INTO emp_audit values (user, ’ D’, now(), NEW.PURVIEW);
END IF;
END
3 结语通过城市规划管理信息系统的开发与运行可知,运用数据库存储过程与触发器技术, 不仅可提高系统的执行效率, 而且充分考虑了安全问题, 从而保证了系统在技术方面的领先性、实用性和安全性。随着标准化工作的进行,触发器机制将越来越完善,可移植性将越来越好,触发器的主动性功能将会越来越强。因此,通过使用触发器与存储过程来实现各种主动服务的功能具有广阔的前景。
| [1] |
赵松涛.
Oracle9i数据库系统管理[M]. 北京: 人民邮电出版社, 2003.
|
| [2] |
王海亮, 林立新, 于三禄, 等.
Oralce10gPL/SQL编程[M]. 北京: 中国水利水电出版社, 2004.
|
2007, Vol. 21
