Technical Blog Post
Abstract
让系统触发器识别调用者
Body
让系统触发器识别调用者
—增强IBM DB2 for i触发器程序的逻辑
原文链接:
http://www.ibmsystemsmag.com/ibmi/january09/technicalcorner/24456p1.aspx
触发器是一种重要的数据库资源,可以用来实现业务逻辑。当表中的数据发生改变时,就会引发触发器的执行。触发器的执行可以发生在数据操作完成之前或之后。甚至可以创建一种触发器,用来替代数据操作请求(INSTEAD OF TRIGGER)。随着业务规则变得越来越复杂,触发器的数量和复杂性通常也随之增长。
本文中,我将展示如何使用获取作业信息的API(QUSRJOBI())来改进IBM DB2 for i上触发器程序的逻辑。通过使用QUSRJOBI()API,触发器程序能够确定是哪个应用程序驱动了数据操作,从而引发了触发器的执行。这些知识使得触发器更符合它的业务规则。
基础介绍
触发器是一系列自动执行的动作,当特定的表或视图上发生一个特定的事件时被触发执行。这个事件可以是一个插入,更新,删除或者读取操作。触发器能在事件发生之前或者之后运行。DB2 for i支持SQL插入,更新,删除和读取操作的触发器。在DB2 for i上有两种触发器程序:系统触发器和SQL触发器。
系统触发器是一些由用户编写和创建的程序。这些程序可以通过高级语言或控制语言来实现。系统触发器是通过添加物理文件触发器(ADDPFTRG)和删除物理文件触发器(RMVPFTRG)的系统命令来安装和删除的。当添加一个触发器时,可以通过设置触发时间(TRGTIME)的命令参数来指定触发器程序在数据操作之前或者之后被调用。
系统触发器能够确定引发触发器的应用程序所使用的确认控制级别(commitment-control level),并使用这些信息去设置一个相匹配的隔离级别(isolation level)。同样,IBM推荐用户使用ACTGRP(*CALLER)来创建触发器程序,以允许其在调用者的激活组(activation group)中运行。通过设置隔离级别和激活组来匹配调用者的环境,系统触发器将参与到事务之中,从而避免了不必要的锁冲突和确认控制问题。
当一个相同的SQL操作上有多个触发器时,这些触发器按照以下顺序来触发:首先是系统触发器(通过ADDPFTRG命令来安装)和用MODE DB2ROW语句建立的SQL触发器,按照它们被创建的顺序触发。其次是用MODE DB2SQL(默认语句)建立的SQL触发器,也按照它们被创建的顺序依次触发。
如果一张表被拷贝或者恢复到一个不同的库,自引用(Self-referencing)触发器就可能失效。当触发器失效时,引发触发器的操作(删除,插入或者更新)将会失败,并返回SQLCODE -7048。可以使用显示文件描述(DSPFD)命令来检查特定表上是否存在触发器及其状态。失效的触发器必须被删除和重建,但如果同一张表相同的SQL操作上有多个触发器,那么触发器的触发顺序可能会被改变。
SQL触发器是基于SQL语言的。CREATE TRIGGER SQL语句用来指定触发器选项和触发器主体。数据库管理器在QTEMP库里生成相应的ILE C代码,用于创建ILE C模块和ILE C触发器程序。创建语句中包含一些选项,可以用来指定触发器在引发它执行的数据操作之前,之后或者替代它执行。SQL触发器有内置的确认控制识别机制,对于引发触发器的SQL语句的代码,可以识别并匹配它们的隔离级别。SQL触发器程序是用ACTGRP(*CALLER)来建立的,所以它们运行在调用者的激活组之中。
尽管数据库代表用户为SQL触发器建立程序,但用户仍然需要对创建程序(CRTPGM)和ADDPFTRG命令有*USE权限。否则,CREATE TRIGGER语句将失败,并返回SQLCODE -552和SQLSTATE 42502。关于更多的错误信息,请参考Insider’s Tip for SQL Message Failures。
触发器的设置和安装
代码样例1提供了指令去创建一个触发器。代码样例2介绍了如何去创建一个样例企业数据库,创建并安装触发器程序,创建存储过程来驱动触发器,以及执行SQL语句来引发触发器执行。
代码样例2中的触发器示例程序是在DB2样例企业数据库上建立的。触发器程序捕获了引发触发器的程序的名字和其所在的库,以及引发触发器的SQL语句文本。这些数据同当前时间戳,基表名和基库名一起被插入到一张ACTIVITY表中。
这个例子显示了数据如何被直接插入或者从两个不同的存储过程中插入。借助于QUSRJOBI()API,触发器程序能区分不同的场景。这种区分使其在单个触发器程序内实现了不同的业务逻辑。
为了让你能够创建一张表去演示触发器程序如何使用QUSRJOBI()来了解调用触发器的环境,我提供了以下的样例代码:
DROP TABLE ACTIVITY;
CREATE TABLE ACTIVITY (TRIGGER_TIME TIMESTAMP,
TABLE_NAME CHAR(10),
TABLE_LIBRARY CHAR(10),
PROGRAM_NAME CHAR(10),
PROGRAM_LIBRARY CHAR(10),
SQL_STMT VARCHAR(3000)
ALLOCATE(256) );
执行语句去引发触发器:
CALL NEW_ORDER();
CALL RECURRING_ORDER();
INSERT INTO SALES VALUES(CURRENT DATE, ‘LEE’, ‘Quebec’, 4);
检查触发器的activity表(见图1)
SELECT * FROM ACTIVITY;
这个例子可以在V5R3以上版本的IBM i 操作系统上运行。
SQL触发器是怎样的呢?
本文中,我描述了两种触发器,但重点讲的是系统触发器,因为SQL触发器不能使用QUSRJOBI的技术。调用QUSRJOBI() API需要使用SQL,而使用SQL会混淆调用触发器程序的应用程序的信息。
识别调用者
QUSRJOBI() API提供了很多有用的SQL信息,可以用来检查其他的作业,或者检查调用作业的状态信息。现在你应该知道触发器程序是如何通过使用这个API来识别它的调用者了。
这项技术也可以用在外部存储过程和外部函数上,但由于触发器的操作不能提供参数接口,因此在触发器程序中使用它是最有用的。
获取更多关于DB2 for i上触发器以及QUSRJOBI()API的信息,请参阅以下资源:
- DB2 for i SQL 参考 (6.1): http://publib.boulder.ibm.com/infocenter/iseries/v6r1m0/topic/db2/rbafz…
- Database SQL 编程 (6.1): http://publib.boulder.ibm.com/infocenter/iseries/v6r1m0/topic/rzajp/rza…
- 获取作业信息 (QUSRJOBI) API: http://publib.boulder.ibm.com/infocenter/iseries/v6r1m0/index.jsp?topic…
UID
ibm11145566