本章节主要介绍在 DM 数据库中触发器的使用。
一、适用场景
软件 | 版本 |
---|---|
操作系统 | Redhat 7 及以上版本 |
DM 数据库 | DM 8.0 及以上版本 |
CPU 架构 | x86、ARM、龙芯、飞腾等国内外主流 CPU |
二、操作方法
2.1 表级触发器
表级触发器的触发动作是三种数据操作命令,即 INSERT、DELETE
和 UPDATE
操作。
- 创建触发器,如下所示:
CREATE OR REPLACE TRIGGER TRG_NAME [WITH ENCRYPTION]
BEFORE|AFTER|INSTEAD OF
INSERT OR DELETE OR UPDATE [OF 列名]
ON TABLE_NAME
FOR EACH ROW [WHEN 条件] --行级触发器中,此子句一定不能省略
BEGIN
PRINT 'INSERT OR DELETE OR UPDATE OPERATION ON TABLE_NAME';--要执行的SQL。
END;
以下“[]”内容为可选项:
- [WITH ENCRYPTION]:对数据进行加密,加密以后,无法看到触发器里的 sql 语句内容。
- UPDATE [OF 列名]:如果指定了 UPDATE 命令,还可以进一步指定当表中的哪个列受到 UPDATE 命令的影响时激发该触发器。
- FOR EACH ROW [WHEN 条件] :对于元组级触发器,可以用一个 WHEN 子句来限制针对当前记录是否执行该触发器。WHEN 子句包含一条布尔表达式,当它的值为 TRUE 时,执行触发器;否则,跳过该触发器。
行级触发器,对触发命令所影响的每一条记录都激发一次。
CREATE OR REPLACE TRIGGER TRG_NAME
AFTER INSERT OR DELETE OR UPDATE ON TABLE_NAME
FOR EACH STATEMENT -- 语句级:此子句可省略
BEGIN
PRINT 'INSERT OR DELETE OR UPDATE OPERATION ON TABLE_NAME';--要执行的SQL
END;
语句级触发器,对每个触发命令执行一次。
- 创建
BEFORE
触发器,该触发器在插入一条记录前,将记录中第一列 READER_ID 的值加 1。如下所示:
--进入数据库 OTHER 模式
SET SCHEMA OTHER;
--创建 BEFORE 触发器
CREATE OR REPLACE TRIGGER TRG_INS_BEFORE
BEFORE INSERT ON OTHER.READER
FOR EACH ROW
BEGIN
:NEW.READER_ID:=:NEW.READER_ID+1;
END;
插入记录前:
插入一条记录:
insert into OTHER.READER(READER_ID, NAME, AGE, GENDER, MAJOR)
VALUES(13, 'test', 20, 'F', 'History');
COMMIT;
插入记录后:
插入的 READER_ID 值为 13 ,插入时触发:NEW.READER_ID:=:NEW.READER_ID+1
,提交的 READER_ID 值为 14。
- 创建 AFTER 触发器,该触发器在插入一条记录后,将插入的值以及操作类型记录到用于审计的表
T_TEMP
中。如下所示:
CREATE TABLE T_TEMP(C1 INT,C2 CHAR(20));
CREATE OR REPLACE TRIGGER TRG_INS_AFTER
AFTER INSERT ON OTHER.READER
FOR EACH ROW
BEGIN
INSERT INTO T_TEMP VALUES(:NEW.READER_ID, 'INSERT ON READER');
END;
插入一条记录:
insert into OTHER.READER(READER_ID, NAME, AGE, GENDER, MAJOR)
VALUES(15, 'test1', 22, 'F', 'Computer');
COMMIT;
插入记录后:
提交后插入数据到表 T_TEMP 中。
- 创建
INSTEAD OF
触发器,该触发器在动作触发的时候,替换原始操作,INSTEAD OF 允许建立在视图上,并且只支持行级触发。如下所示:
--创建视图 v1
create table t1(a int,b int);
insert into t1 values(10,10);
insert into t1 values(11,11);
create view v1 as select * from t1;
--在视图 v1 上创建 INSTEAD OF 触发器。
CREATE OR REPLACE TRIGGER tri1
INSTEAD OF UPDATE ON v1
BEGIN
insert into t1 values(111,111); --替换动作
END;
执行 UPDATE
动作:
update v1 set a=100 where a=10;
查询结果:
更新操作并没有成功,而是被触发器中的替换动作替换了。
2.2 时间触发器
时间触发器属于一种特殊的事件触发器,可以定义一些有规律性执行的、定点执行的任务。
- 创建时间触发器,在屏幕上每隔一分钟输出一行
HELLO WORLD
。如下所示:
CREATE OR REPLACE TRIGGER timer2
AFTER TIMER on database
for each 1 day for each 1 minute
BEGIN
print 'HELLO WORLD';
END;
时间触发器的最低时间频率精确到分钟级,定义很灵活,完全可以实现数据库中的代理功能,只要通过定义一个相应的时间触发器即可。在触发器体中定义要做的工作,可以定义操作的包括执行一段 SQL 语句、执行数据库备份、执行重组 B 树、执行更新统计信息、执行数据迁移 (DTS)。
2.3 触发器管理
- 每个触发器创建成功后都自动处于允许状态 (ENABLE),当不想被触发,但是又不想删除这个触发器。这时,可将其设置关闭触发器 (DISABLE)。
--关闭触发器
ALTER TRIGGER OTHER.TRG_INS_AFTER DISABLE;
--打开触发器
ALTER TRIGGER OTHER.TRG_INS_AFTER ENABLE;
- 触发器删除
DROP TRIGGER OTHER.TRG_INS_AFTER;
- 触发器查看
--查看当前数据库的全部触发器
SELECT * FROM DBA_TRIGGERS;
--查看当前用户有权限访问的触发器
SELECT * FROM ALL_TRIGGERS;
--查看示当前用户所拥有的触发器
SELECT * FROM USER_TRIGGERS;
输出结果:
注意1.<触发器名> 是触发器的名称,它不能与模式内的其他模式级对象同名。
2.可以使用 OR REPLACE 选项来替换一个触发器,但是要注意被替换的触发器的触发表不能改变。如果要在同一模式内不同的表上重新创建一个同名的触发器,则必须先删除该触发器,然后再创建。
3.INSTEAD OF 触发器仅允许建立在视图上,并且只支持行级触发。
4.表级触发器不支持跨模式,即 <触发器名> 必须和 <触发表名>、<触发视图名> 的模式名一致。
5.水平分区子表、HUGE 表不支持表级触发器。
6.同类触发器的激发顺序没有明确的定义。如果顺序非常重要的话,应该把所有的操作组合在一个触发器中。
7.在 DM 的数据守护环境下,备库上定义的触发器是不会被触发的。
三、参考文献
更多 SQL 语言使用说明,请参考《DM8_SQL 语言使用手册》,手册位于数据库安装路径 /dmdbms/doc
文件夹下。如有其他问题,请在社区内咨询。