1、触发器简介
触发器可以看作是一种特殊的存储过程,它定义了一些与数据库相关的事件发生时所执行的的代码。
触发器和存储过程的区别:定义触发器和存储过程的语法相似,但存储过程需要用户亲自调用,而触发器则由触发事件调用。
触发事件:指能够引起触发器运行的操作的就被称为触发事件。
2、触发器语法
创建一个触发器:
create [or replace] trigger 触发器名称
[before/after/instead of] 触发事件
on [表明/视图名/数据库名...]
[for each row][when 触发条件]
[declare]
[变量声明部分;]
begin
程序代码部分;
end [触发器名称];
- trigger:创建触发器的关键字字
- before/after/instead of:触发时期的关键字;before:执行触发事件之前触发;after:执行触发事件之后触发;instead of:替代触发器,可用于通过视图操作表数据
- for each row:指定触发器为行级触发器
Oracle所支持的触发器类型:
- 语法级触发器:无论DML语句影响多少行数据,它所引起的触发器都只执行一次。
- 行级触发器:当DML语句对每一行数据进行操作时都会引起该触发器运行
- 替换触发器:该触发器是定义在视图上,用来替换所使用实际语句的触发器
- 用户事件触发器:是指与DDL操作或用户登陆、退出数据库等事件相关的触发器。
- 系统事件触发器:是指在Oracle数据库系统的事件中触发的触发器
3、语句级触发器
语句级触发器是针对一条DML语句而执行的触发器。在语句级触发器中,不适用for each row 子句,也就是说无论数据操作影响多少行,触发器都只会执行一次。
(1)创建一个日志表dept_log,用于存储对表dept的各种数据操作信息。
create table dept_log
(
operate_tag varchar(10),
operate_time date
);
(2)创建触发器,当对表dept执行增删改操作时,在日志表dept_log表中,存储记录。
create or replace trigger tri_dept
before insert or update or delete
on dept
declare
var_tag varchar2(10);
begin
if inserting then
var_tag :='插入';
elsif updating then
var_tag :='修改';
elsif deleting then
var_tag :='删除';
end if;
insert into dept_log values(var_tag,sysdate);
end;
(3)执行增删改操作,查询结果。
select * from dept_log;
OPERATE_TA OPERATE_TIME
---------- --------------
删除 14-1月 -19
删除 14-1月 -19
插入 14-1月 -19
4、行级触发器
行级触发器会针对DML操作所影响的每一行数据都执行一次触发器。创建该触发器时,必须在语法中 使用for each row 这个选项,使用行级触发器最典型的一个应用就是给数据表生成主键值。
例:使用行级触发器生成数据表中的主键值
(1)创建一个表,用于存储商品种类,其中包含商品序列号和商品名称
create table commodity
(
id int primary,
good_name varchar2(50);
);
(2)创建一个序列,用于生成不重复的有序值。
create sequence seq_id;
(3)创建一个触发器,用于为commodity表的id列赋值
create or replace trigger tir_insert_comm
before insert
on commoidty
for each row
begin
select seq_id.nextval
into :new.id
from dual;
end;
5、替换触发器
替换触发器定义在视图上,通过在替换触发器中编写适合的代码可以对构成视图的各个基表进行操作。
创建并使用替换器:
(1)创建一个视图
create view view_emp_dept
as select empno,ename,dept.deptno,dname,job,hiredate from emp,dept
where emp.deptno=dept.deptno;
(2)创建该视图的替换触发器,作用与insert 事件上
create or replace trigger tri_insert_view
instead of insert on view_emp_dept for each row
declare
row_dept dept%rowtype;
begin
select * into row_dept from dept where deptno=:new.deptno;
if sql%notfound then
insert into dept(deptno,dname)values(:new.deptno,:new.dname);
end if;
insert into emp(empno,ename,deptno,job,hiredate) values(:new.empno,:new.ename,:new.deptno,:new.job,:new.hiredate);
end;
(3)在视图中插入一条记录,查询结果
insert into view_emp_dept(empno,ename,deptno,dname,job,hiredate) values(8888,'张三',50,'信息','manager',sysdate);
select * from view_emp_dept where empno=8888;
EMPNO ENAME DEPTNO DNAME JOB HIREDATE
---------- ---------- ---------- -------------- --------- --------------
8888 张三 50 信息技术部 manager 14-1月 -19
6、删除触发器
drop trigger 触发器名称;