1 触发器简介
1) 触发事件
2) 触发条件
3) 触发操作
. 触发器代码的大小不能超过32k,如果使用大量代码建立触发器,应该先建立存储过程,然后再触发器中使用call语句调用存储过程。
. 触发器中正能含有select ,insert,update 和delete 语句,而不能含有ddl 语句,和事物控制语句。
2 建立dml 触发器
1) 触发时机
before,after 表示在执行dml操作之后触发器
2)触发事件
insert ,update 和delete 操作。也可以使用书法事件
3) dml 触发器是针对特定表进行的 因此必须制定dml 操作所对应的表
4) 触发器类型 用于指定当触发器事件之后,需要执行几次触发器操作。如果指定语句触发器类型
那么会执行一次触发器代码:如果指定行触发器类型,则会在每个被作用行上执行一次触发器代码。
5) 触发条件
用于指定执行行触发器代码的条件,只有为ture时,才会执行行触发器代码。
6) 如果使用pl/sql 存储过程,java 存储过程,或外部处处过程需要在触发器操作部分直接使用call
7) dml 触发器触发顺序
(1)dml 触发器在单行数据上的触发顺序。
对于单行数据而言,无论是语句此触发器,还是行触发器,触发器代码实际只执行一次,并且执行
顺序为before 语句触发器,before 行触发器,dml 操作,after 行触发器,after 语句触发器
(2) dml 触发器在多行数据上的触发顺序
before 语句触发器
before 行触发器
after 行触发器
before行触发器
after 行触发器
after语句触发器
语句触发器只被执行一次,而行触发器在每个行上都执行一次。
2) 语句触发器
当审计dml 操作,或确保dml操作安全执行时,可以使用语句触发器
1 建立before 语句触发器
create or replace trigger tr_sec_emp
before insert or update or delete on emp
begin
if to_char(sysdate,'DY','nls_dtate_language=AMERICAN') in ('sat','sun') then
railse_application_error(-200001,'不能在休息日改变雇员信息');
end if;
end;
2 使用条件谓词
inserting ,updating ,deleting
create or replace trigger tr_sec_emp
before insert or update or delete on emp
begin
if to_char(sysdate,'DY','nls_date_language=american')
in('sat','sun') then
case
when inserting then
raise_application('-20001','inserting');
when updating then
raise_application('-20002','updating');
when deleting then
raise_application('-20003','deleting');
end case;
end if;
end;
3 建立after 语句触发器
为了dml 操作,或者dml 操作后执行汇总运算
create table aduit_table(
name varchar2(20),ins int,upd int,del int,
starttime date,endtime date
);
create or replace trigger tr_aduit_emp
after insert or update or delete emp
declare
v_temp int;
begin
select count(*) into v_temp from aduit_table
where name='emp';
if v_temp=0 then
insert into audit_table values
('emp',0,0,0,sysdate,null);
end if;
case
when inserting then
update aduit_table set ins=ins+1,endtime=sysdate where name='emp';
when updating then
update audit_table set upd=upd+1,endtime=sysdate where name='emp';
when deleting then
update aduit_table set del=del+1,endtime=sysdate where name='emp';
end;
3) 行触发器
审计数据变化可以使用行触发器
1 建立不before 行触发器
为了取保数据符合商业逻辑或企业规则,对输入的数据进行复杂的约束,可以使用before行触发器
create or replace trigger tr_emp_sal
before update of sal on emp
for each row
begin
if :new.sal<:old.sla then
raisse_application_error(-200010,'工资只涨不降');
end if;
end;
2) 建立after 行触发器
为了审计dml 操作,可以使用语句触发器或oracle 系统提供的审计功能,而为了审计数据变化
,则应该使用after 行触发器
create table audit_emp_change(
name varchar2(10),odl number(6,2),
newsal number(6,2),time date);
create or replace trigger tr_sal_change
after update of sal on emp
for each row
declare
v_temp int;
begin
select count(*) into v_temp from audit_emp_change where name=:old.ename;
if v_temp =0 then
insert into audit_emp_change
values(:old,ename,:old.sal,:new,sal,sysdate);
else
update audit_emp_change
set oldsal=:old.sal,newsal=:new.sal,time=sysdate where name=:old.ename;
end if;
end;
)
3) 限制行触发器
当使用行触发器,默认情况下会咱每个被作用行上七星一次触发器代码,为了时得再特定条件下执行行触发器代码,需要使用when 子句
create or replace trigger tr_sal_change
after update of sal on emp
for each row
when(old.job='salesman')
declare
v_temp int..
2 dml 触发器使用注意事项
触发器代码不能从触发器所对应的基表中读取数据
3 dml 触发器
为了保证数据库满足特定的商业规则或企业逻辑,可以使用约束,触发器和子程序。约束性能最好,实现最简单,所以为售选,如果触发器不盟实现,可以选择触发器。
dml 触发器可以用于实现数据安全保护,数据审计,数据完整性,参照完整性,数据复制等功能。
1) 控制数据安全
create or replace trigger tr_emp_time
before insert or update or delete on emp
begin
if to_char(sysdate,'hh24') not between '9' and '17' then
raise_application_error(-20101,'not work time');
end if;
end;
2) 实现数据审计
使用数据审计只能审计sql 操作,而不会记载数据变化
audit insert,update,delete on emp by access
3)实现数据完整性
首选约束 alter table emp add constraint ck_sal check (sal>=800),但是在有些情况下只能使用触发器来实现数据完整性
create or replace trigger tr_check sal
before update of sal on emp
for each row
when (new.sla<old.sal or new.sal>1.2* old.sal)
begin
raise_application_error(,,,,,,)
end;
3) 使用引用完整性
采用 on delete cascade 可以进行集联删除,但是却不能进行集联更新。采用触发器实现集联更新
create or replace trigger tr_update
after update of sal on emp
for each row
begin
update emp set depno=:new.deptno where dentno=:old.deptno;
end;
4 建立instead of 触发器
对于简单视图可以直接进行insert update 和delete 等操作,但是对于复杂视图不允许进行insert,update 和delete 操作。
满足一下条件的为复杂视图
具有操作集合符 union,union all ,intersect,minus
具有分组函数 min,max,avg,sum,count
具有group by connect 编译 或start with
具有distinct
具有连接
为了在复杂视图上执行dml 操作,必须要基于instead-of 触发器,建立instead-of 触发器后,就可以基于复杂视图执行insert,update和delete 语句。
instead of 选项只使用于视图
基于视图建立触发器时,不能定义before 和 after
在建立视图时不能指定 with check option
当建立instead of 触发器时,必须指定for each row 选项
1) 建立复杂视图dept_emp
create or replace view dept_emp as
select a.deptno,a.dname,b,empno,b,ename
from dept a,emp b
where a,deptno=b.deptno;
2) 建立 instead-of 触发器
create of replacee trigger tr_instead_of_dept_emp
instead of insert on dept_emp
for each row
declare
v_temp int;
beegin
select count(*) into v_temp from dept where deptno=:new.deptno;
if v_temp=0 then
insert into dept(deptno,dname) values(:new.deptno,:new.dname);
end if;
select count(*)into v_temp from emp where empno=:new.empno;
if v_temp=0 then
insert into emp(empno,ename,deptno)
values(:new.deptno,:new.ename,:new.deptno);
end if;
end;
可以对视图执行insert 操作了
insert into dept_emp values(50,'admin','1223','mary')
5 管理触发器
1) 显示触发器信息
select trigger_name,status from user_triggers
where table_name='emp';
2)禁止触发器
alter trigger tr_check_sal disable;
3) 激活触发器
alter trigger tr_check_sal enable;
4) 禁止或激活表上的所有触发器
alter table emp disable all triggers;
alter table emo eanble all triggers;
5)重新编译触发器
alter trigger tr_check_sal compile;
6) 删除触发器
drop trigger tr_check_sal;