一、触发器
1.三种操作: delete update insert
2.两个临时表: :new :old
3.两个时间点: after before
4.两种重要模式: 行级 语句级
5.条件: when
Oracle中的触发器比SQL Server要复杂;
SQL Server中增删改操作只会触发一个事件,但在Oracle中会触发两个事件。
以delete为例,Oracle有个删除前事件 before 、删除后事件 after。
Oracle触发器分:前触发、后触发
1.什么是触发器?
(1) 触发器是一种特殊的存储过程;
(2) 触发器不能被直接调用,也不是手动启动,而是由事件来触发;--增删改
(3) 触发器经常用于加强数据的完整性约束和业务规则等。
(4) 触发器具备事务的功能。
简单点说:触发器就是个开关,负责灯的亮与灭,你动了它就亮了。
Oracle触发器比SQL Server的要复杂,有触发前before与触发后after。
2.创建触发器语法(史上最难的oracle语法,没有之一)
create [or replace] trigger trigger_name
after|before|instead of --instead反向
[insert][[or] update [of 列列表]][[or] delete]
on table表或view --视图使用率
[referencing{:old [as] old/:new [as] new}] --引用新表老表
[for each row] --行级模式
[when(condition)] --条件
pl/sql_block; --pl/sql语句(begin...end)
insert after before
--案例:
insert into emp values(…,张三,…,0,……);
==>去 :new
create or replace trigger trig_name
after insert
on emp
for each row
begin
if(:new.sal=0) then
dbms_output.put_line('警告:干活不能不给薪水');
else
dbms_output.put_line('已插入记录');
end if;
end;
3. 触发器组成三部分:
a. 触发器语句(事件)--定义激活触发器的DML(数据操作语言)事件和DDL(数据定义语言)事件;
b. 触发器限制 ---执行触发器的条件,该条件为真才能激活触发器;
c. 触发器操作(主体)--包含SQL语句和代码,它们在发出了触发语句且触发限制的值为真是才运行。
注示:序列通过前触发保存到数据库中。
4. 前触发与后触的原理图
5. 在级联表中创建触发器案例
--李斯文不能删
(什么时候触发?a.delete时; b.when 条件满足时; c.代码中写明)
create or replace trigger t_studel
after delete
on stuinfo
for each row
begin
if :old.stuname='李斯文' then
--抛出异常
raise_application_error(-20010,'该学生不能删!!!');
end if;
end;
delete from emp;
--李斯文不能删,不能改
after delete or update
--怎么知道是(insert\delete\update)哪个操作?
……
begin
case
when deleting then
--删除时
if :old.stuname='李斯文' then
raise_application_error(-20010,'该学生不能删!!!');
end if;
when updating then
--修改时
if :old.stuname='李斯文' then
raise_application_error(-20011,'该学生不能修改!!!');
end if;
when inserting then
--插入时
if :old.stuname='张杨' then
raise_application_error(-20012,'该学生你也敢招!!!');
end if;
end case;
end;
insert 李超 :new
insert before ----> if (:old 李超 ---> 插入到表中去 ==没用
if (:new 李超 ---> 没插入到表中
before--->:new
insert after ----> if (:old 李超) ---> 插入到表中去
if (:new 李超) ---> 没插入到表中
before | after insert ----> :new
before | after delete ----> :old
思考:
一个表能创建几个insert\update\delete触发器?
高级点的触发器
--多表联接
1.确定触发器写在哪个表上 on table
2.确定使用哪个触发器insert delete update
3.用after 还是 before,用:new :old
--在stuinfo表中写个delete触发器,指定删除的人名,
直接删除stumarks表中该人的成绩。
create or replace tirgger t_mydel
after delete
on stuinfo
for each row
declare
stu varchar2(22);
begin
stu:=:old.stuno; --将删除的学生的学号赋值给该变量
delete from stumarks where stuno=stu;
end;
--运行下
delete from stuinfo where stuname='李斯文';
注意:
表连接的触发器是比较复杂的,对A表操作触发A表的触发器,同时影到到了B表触发了B表的触发器,依次类推下去...
建议:表跟表关联频繁时,建议甚用触发器。
行级触发器与语句级触发器:
--案例2
create or replace tirgger t_mydel
after delete
on stuinfo
for each row
begin
dbms_output.put_line('删的好!');
end;
--执行(删除了一条记录,结果显示一条'删的好')
delete from stuinfo where stuname='李文才';
--执行(删除了整个表中的记录,显示N条'删的好')
delete from stuinfo
--说明:这就是讲解行级触发器。
--行级触发器:一条条的删,删一条就触发一个行级触发器。
思考:
如果将[for each row]代码删除,执行看效果。--语句级触发器。
--语句级触发器:执行一条触发一次。
标识列:序列+触发器
--创建个新表,准备往里面插入记录,使用触发器和序列。
create table tb_715( sid number, sname varchar2(22) )
--执行插入操作
insert into tb_715(sid,sname) values(1,'刘帅')
--需求:不写sid,1能帮我自动产生一个序列。
--解决:(1)创建序列
create sequence seq715;
(2)创建个触发器,用前触发,用new表
create or replace trigger t_insert
before insert
on tb_715
for each row
begin
--新表中的id=序列的下一个值
select seq715.nextval into :new.sid from dual;
end;
oracle 11g的语法:
:new.sid:=seq715.nextval;
oracle 10g的语法:
select seq715.nextval into :new.sid from dual;
别用变量,用变量的方法就是11g的写法。
--:new表,将插入的数据先放入到:new表中,确认后放到要更新的表。
--:old表,将不要的数据先放入到:old表中,确认不要了再清除:old表。
--注意::new表和:old表中至始至终就只有一条数据,那请问有多少个列?触发器的表有多少个列,:new表和:old表就有多少个列。
思考:
1.触发器删掉,表还在不在?
2.表删掉了,触发器还不在?
3.表删掉了,视图还不在?
SQL Server不在;Oracle在,oracle中是分开的。