gbase8s触发器使用
触发器创建位置
表 、视图
触发事件
insert select update delete
触发时机
before 、alter 、for each row
触发动作列表
insert select update delete
触发作用域
语句级、行级
触发器状态
enable disable
说明
before after 均为 语句级触发器,即触发列表动作只执行一次
before after 因为是语句级触发器,没有 new值 old值的说法
在触发列表中不支持条件判断变量定义等操作,需要使用存储过程
在触发列表中不支持 抛出异常或者处理异常,需要使用存储过程
例如
create table t1(c1 int ,c2 varchar(10));
create table t_cont(c1 int);create trigger t_before insert on t1
before (
insert into t_cont select count(1) from t1
);
在插入之前统计该表的总行数
当有一些判断逻辑时可以在触发列表中调用存储过程实现
例如
drop table if exists t1;
drop table if exists t_cont;
create table t1(c1 int ,c2 varchar(10));
create table t_cont(c1 int);
create procedure p1()
define i,j int;
let i=90;
let j=(select count(1) as cnt from systables where 1=1);
if i < j then
insert into t_cont values(j);
end if
end procedure;create trigger t_before insert on t1
before (
execute procedure p1()
);
after与before使用上逻辑一样
for each row 触发器
for each row 为行级触发器,即每一行都会触发触发列表的操作
在使用中一般需要获取到 new old值
例如 ,将插入的数据触发插入到另一张表
drop table if exists t1;
drop table if exists t2;
create table t1(c1 int);
create table t2(c1 int);
drop trigger if exists trri1;
create trigger trri1 insert on t1 referencing NEW AS new
FOR EACH ROW(
insert into t2 values(new.c1)
);
同样,当需要处理逻辑时,仍然需要调用存储过程来实现
在创建存储过程中需要额外使用referencing NEW AS new /old as old来引用新旧值
例如
drop table if exists t1;
drop table if exists t2;
create table t1(c1 int);
create table t2(c1 int);
drop trigger if exists trri1;
drop procedure if exists p1;create procedure p1() REFERENCING NEW AS NEW for t1
IF new.c1 = 1 THEN
raise exception -746 ,0,'Error: this is error';
END IF;
end procedure;create trigger trri1 insert on t1 referencing NEW AS new
FOR EACH ROW(
execute procedure p1() with trigger references
);
在 gbase8s规则中
delete select 操作 只有old
insert 操作只有new
update 操作同时存在 old new
相比oracle 在for each row 触发时 是没有 before 或者after 修饰,也就是说在gbase8s中for each row没有触发前后的说法,仍然可以通过一些用例简单测试下触发时机
drop table if exists t1;
drop table if exists t2;
create table t1(c1 int);
create table t2(c1 int);
drop trigger if exists trri1;
create trigger trri1 insert on t1 referencing NEW AS new
FOR EACH ROW(
insert into t2 select count(1) as cnt from t1
);
查询t2 时 结果为1
可见测试结果触发时机更倾向于 after
或者
drop table if exists t3;
drop table if exists t4;
create table t3(c1 int ,c2 datetime year to second);
create table t4(c1 int ,c2 datetime year to second);drop procedure if exists p2;
create procedure p2()
define dt1 datetime year to second;
system 'sleep 10';
select DBINFO('utc_to_datetime',sh_curtime) into dt1 from sysmaster:sysshmvals;
insert into t4 values(1,dt1);
end procedure;create trigger trri6 insert on t3
FOR EACH ROW (
execute procedure p2()
);
在另一session开启脏读的情况下观察t3 t4表数据
结果为 t3先插入数据,十秒后t4插入数据
可见触发时机更倾向于after 触发
在实际使用中可同时存在before、after、以及for each row 触发器,顺序必须为
before、for each row、 after
例如
create trigger trri1 insert on tab1 referencing NEW AS new
before (
insert into tab2 values(1)
)
FOR EACH ROW (
insert into tab3 values(new.c1)
)
after (
insert into tab4 values(1)
);
多个触发器的触发顺序
CREATE TABLE taba (a INT, b INT, c INT, d INT);
假设在列 a 和 c 上定义 trig1,在列 b 和 d 上定义 trig2 。如果两个触发器都指定BEFORE 、FOR EACH ROW 和 AFTER 操作,则按以下顺序执行触发器操作:
- 触发器的 BEFORE 操作列表(a 、 c)
- 触发器的 BEFORE 操作列表(b 、d)
- 触发器的 FOR EACH ROW 操作列表(a 、c)
- 触发器的 FOR EACH ROW 操作列表(b、 d)
- 触发器的 AFTER 操作列表(a 、 c)
- 触发器的 AFTER 操作列表(b 、 d)