如何在DB2 Universal Database中暂时禁用触发器(1)
发表于:2007-07-13来源:作者:点击数:
标签:
简介 有时您会想暂时禁用表上的触发器。例如,尽管您可能需要触发器执行日常的 SQL 操作,但可能不希望在运行特定脚本时触发那些触发器。标准做法是删除触发器,当再次需要它时再重新创建,但如果您必须跟踪许多触发器,那就有点为难了。(现在,我该把那些
简介
有时您会想暂时禁用表上的触发器。例如,尽管您可能需要触发器执行日常的 SQL 操作,但可能不希望在运行特定脚本时触发那些触发器。标准做法是删除触发器,当再次需要它时再重新创建,但如果您必须跟踪许多触发器,那就有点为难了。(现在,我该把那些触发器的源代码保存到哪里呢?)
本文提供了三种解决这个问题的方法:
- 方法 1:对特定用户禁用触发器
- 方法 2:用框架来允许禁用触发器
- 方法 3:使用 SQL 存储过程维护触发器
每种方法都有其优缺点,但我们将这方面的 讨论留到文章末尾。
方法 1:对特定用户禁用触发器
用来执行数据库维护任务的用户标识通常与用于应用程序的用户标识不同,这种方法利用了这一情况。要使这种方法有效,您只需选择在不希望触发触发器时要使用的用户标识。
example1.db2脚本中的 SQL 向您演示了这种方法。
设置
要设置这个示例:
- 创建两个表
t1
和 t2
。我们将在 t1
上创建一个样本触发器,它将引起对 t2
进行插入操作。
clearcase/" target="_blank" >cccccc border=1>
CREATE TABLE db2admin.t1 (c1 int)
CREATE TABLE db2admin.t2 (c1 int)
|
- 创建触发器:
CREATE TRIGGER db2admin.trig1
AFTER INSERT ON db2admin.T1
REFERENCING NEW AS o
FOR EACH ROW MODE DB2SQL
WHEN (USER <> 'ADMINISTRATOR')
BEGIN ATOMIC
INSERT INTO db2admin.t2 values (o.c1);
END
|
这个触发器很简单。每当连接的用户标识(由 USER 专用寄存器返回的)与 ADMINISTRATOR 不匹配时,则将插入到 t1
中的值也插入到 t2
。因此,当不想触发触发器时,以用户 ADMINISTRATOR进行连接以执行您的任务。
测试示例
- 在创建了表
t1
、 t2
和触发器 trig1
之后,以不同于 ADMINISTRATOR 的任何用户进行连接并将值插入 t1
。
INSERT INTO db2admin.t1 VALUES (111)
|
- 验证该值已由触发器复制到了表
t2
中:
SELECT * FROM db2admin.t2
C1
-----------
111
1 record(s) selected.
|
- 接下来,以用户 ADMINISTRATOR 连接,并尝试再次插入值:
INSERT INTO t1 VALUES (222)
|
- 验证表
t2
未更改,因为触发器未被激活:
SELECT * FROM db2admin.t2
C1
-----------
111
1 record(s) selected.
|
方法 2:用框架来允许禁用触发器
本节描述了一个触发器框架,您可以将它用于任何可能需要暂时禁用的触发器。使用框架要求触发器开发人员进行规划并对这种概念取得一致意见,但这样做的结果可以得到该问题非常清晰的解决方案。
example2.db2脚本中的 SQL 向您演示了这种方法。
下面说明了这种机制的工作原理:
- 定义触发器查找表
trigger_state
,它维护一个由触发器的名称和状态(active='Y' 或 'N')所组成的列表
- 在定义触发器时,向
trigger_state
表添加一次查寻(在该触发器的 WHEN 子句中)以确定该触发器是否应该激活
设置
要设置这个示例:
- 创建两个表
t1
和 t2
。我们将在 t1
上创建一个样本触发器,它将引起对 t2
进行插入操作。
CREATE TABLE db2admin.t1 (c1 int)
CREATE TABLE db2admin.t2 (c1 int)
|
- 创建
trigger_state
表。
CREATE TABLE db2admin.trigger_state
(
trigschema VARCHAR(128) not null,
trigname VARCHAR(30) not null,
active char(1) not null
)
|
乍一看,您很可能想在含有 trigschema
和 trigname
列的 trigger_state
表中放置一个主键。目前,我们先不在表上放置任何约束。
- 假定您想要在表
t1
上创建名为 trig1
的触发器。我们要做的第一件事情是向 trigger_state
表注册该触发器:
INSERT INTO db2admin.trigger_state VALUES ('DB2ADMIN','TRIG1','Y')
|
提示:对所有值都使用 大写,与系统目录表保持一致。
- 接下来,为方便起见,我们将创建用户定义的函数(UDF)。当我们创建触发器时,它的用途将变得很明显:
CREATE FUNCTION db2admin.trigger_enabled (
v_schema VARCHAR(128),
v_name VARCHAR(30))
RETURNS VARCHAR(1)
RETURN (SELECT active FROM db2admin.trigger_state WHERE trigschema=v_schema and trigname=v_name)
|
重要:如果查寻失败,则这个函数返回空值。因此,确保正确填写 trigger_state
表,并在调用这个函数时传递正确的参数。
如您所见,该函数将模式和触发器的名称作为输入,以在 trigger_state
表中执行查寻,并返回 active
列中的值。
- 创建触发器:
CREATE TRIGGER db2admin.trig1
AFTER INSERT ON db2admin.T1
REFERENCING NEW AS o
FOR EACH ROW MODE DB2SQL
WHEN (db2admin.trigger_enabled('DB2ADMIN','TRIG1') = 'Y')
BEGIN ATOMIC
INSERT INTO db2admin.t2 values (o.c1);
END
|
这个触发器很简单。当启用它时,插入 t1
的值也会插入到 t2
。但是,在激活它之前,它调用 UDF trigger_enabled()
来确定该触发器是否被禁用。用该函数封装这个查询降低了出错的可能性,尤其是在需要创建许多触发器的情况下。
提示:如果您的触发器已经将 WHEN 子句用于其它条件,则只需用 AND 操作符将条件串到一起。
测试示例
- 首先,我们测试该触发器是否按预期的方式工作:
INSERT INTO db2admin.t1 values (123)
DB20000I The SQL command completed successfully.
|
- 验证
t2
也包含值 123,因为激活了触发器:
SELECT * FROM db2admin.t2
C1
-----------
123
1 record(s) selected.
|
- 现在,我们将禁用该触发器:
UPDATE db2admin.trigger_state SET active='N'
WHERE trigschema='DB2ADMIN' and trigname='TRIG1'
|
- 然后将另一行插入
t1
:
INSERT INTO db2admin.t1 values (456)
|
- 现在,让我们通过确定表
t2
未经更改来验证触发器已被禁用。
SELECT * FROM db2admin.t2
C1
-----------
123
1 record(s) selected.
|
原文转自:http://www.ltesting.net