触发器详解
Posted 喜欢一个人…
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了触发器详解相关的知识,希望对你有一定的参考价值。
1. 触发器的概念:
触发器是存储在服务器中的程序单元,当数据库中某些事件发生时(比如insert\\update\\delete),数据库自动启动触发器,执行触发器中的相应操作。
(1) 触发器是一种特殊的存储过程,具备事务的功能;
(2) 触发器不能被直接调用,而是由事件来触发;--例如:增删改
(3) 触发器常用于加强数据的完整性约束和业务规则等。
简单点说:触发器就是个开关,灯就是开关触发后的操作,触动了开关灯就亮了。
2. 触发事件:
Insert,update,delete,create(创建对象时),alter,drop
logon/logoff(用户的登录或注销时执行触发器)
startup/shutdown(数据库打开或关闭时执行触发器)。
3. 触发时间
before 在指定的事件发生之前执行触发器
after 在指定的事件发生之后执行触发器
4. 触发级别
4.1行级触发
行触发:对触发事件影响的每一行执行触发器,即触发机制是基于行的。改一行数据,触发一次。
eg:增删改的触发器 start
有两个表,Demo,Demo1,以下为建表语句
create table DEMO
(
name1 VARCHAR2(255),
pwd1 VARCHAR2(255),
id VARCHAR2(255)
);
create table DEMO1
(
name1 VARCHAR2(255),
pwd1 VARCHAR2(255),
id VARCHAR2(12)
);
在demo表中增删改,实现在demo1中数据同步,这时需要在demo中添加触发器,以下为触发器代码
CREATE or replace TRIGGER test1 before INSERT OR UPDATE OR DELETE
ON DEMO
FOR EACH ROW BEGIN
case
when inserting then
insert into DEMO1(NAME1,PWD1,ID) values(:new.name1,:new.pwd1,:new.id);
when updating then
update DEMO1 set name1=:new.name1,pwd1=:new.pwd1 where id=:new.id;
when deleting then
delete DEMO1 where name1 =:old.name1;
end case;
END;
简单介绍:
CREATE TRIGGER //触发器名
BEFORE 或者AFTER // 触发事件 后面加(INSERT OR UPDATE OR DELETE )
ON //建立触发器表名
FOR EACH ROW
BEGIN sql语句 END
在demo中运行insert语句,在demo1中查询数据,会发现数据同步,这时发明触发器运行成功,
注:不同服务器触发器的使用,与同服务器触发器的使用大同小异,只是触发器的代码需要更改,以下为触发器代码
CREATE TRIGGER test1 before INSERT OR UPDATE OR DELETE
ON system.demo
FOR EACH ROW BEGIN
case
when inserting then
insert into system1.demo(NAME1,PWD1,ID) values(:new.name1,:new.pwd1,:new.id);
when updating then
update system1.demo set name1=:new.name1,pwd1=:new.pwd1 where id=:new.id;
when deleting then
delete system1.demo where name1 =:old.name1;
end case;
END;
介绍:
ON//本地服务器名字.本地需要建立触发器的表名,以插入为例 insert into system1.demo(NAME1,PWD1,ID) ,system1.demo即:另一服务器名字.对应的表名;
对应以上本地服务器的操作,如发现在system.demo中运行增删改system1.demo中数据实时更新,则说明触发器建立成功
eg:end
关键语句:for each row
--案例1
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
--说明:这就是讲解行级触发器。
--行级触发器:一条条的删,删一条就触发一个行级触发器。
--语句级触发器:执行一条触发一次。
4.2语句触发
语句触发:对触发事件只能触发一次,而且不能该问受触发器影响的每一行的值。既无论这条SQL语句影响多少条记录,触发器都只触发一次。
4.2.1. 创建触发器
create [or replace] trigger trigger_name
after|before|instead of --instead反向
[insert][[or] update [of 列列表]][[or] delete]
on table表或view
[for each row] --行级模式
Begin
--pl/sql语句(begin...end)
End;
案例1:
--创建一个触发器tig_1,当用户删除scott.emp表中的数据时提示。
SQL>create or replace trigger tig_1
after delete
on scott.emp //注意:这里没有用for each row,即不管删除多少条,只触发一次该触发器
begin
if deleting then
dbms_output.put_line(\'有用户删除了emp表中的数据!\');
end if;
end;
案例2:
--创建一个触发器tig_2,当表scott.dept中的deptno列的值发生变化时,自动更新表scott.emp中的deptno列的值,从而保证数据的完整性。
SQL>create or replace trigger tig_2
after update
on scott.emp
for each row
begin
update scott.emp set deptno = :new.deptno
where deptno = :old.deptno;
end;
注意:
这段程序中有两个概念:new和:old, :new代表执行更新操作之后的新表,:old代表执行更新操作之前的旧表。
通过这两张表的使用,可以访问到触发器执行前后表数据的变化。
insert操作只有:new,delete操作只有:old,update操作二者皆有。
:new 和 :old只用于行级触发器。
--:new表,将插入的数据先放入到:new表中,确认后放到要更新的表。
--:old表,将不要的数据先放入到:old表中,确认不要了再清除:old表。
--注意::new表和:old表中至始至终就只有一条数据,那请问有多少个列?触发器的表有多少个列,:new表和:old表就有多少个列。
--案例:
SQL>insert into emp values(…,张三,…,0,……);
SQL>create or replace trigger trig_name
after insert --插入操作之后
on emp --在emp表中
for each row --行级模式
begin
if(:new.sal<=0) then --新表:new中的sal等于0
dbms_output.put_line(\'警告:干活不能不给薪水\');
rollback;(可以用异常:抛异常后回滚数据)
else
dbms_output.put_line(\'已插入记录\');
commit;
end if;
end;
5.触发器组成三部分:
a. 触发器语句(事件)--定义激活触发器的DML事件和DDL事件;
b. 触发器限制 --执行触发器的条件,该条件为真才能激活触发器;
c. 触发器操作(主体)--包含SQL语句和代码,它们在发出了触发语句且触发限制的值为真是才运行。
注示:序列通过前触发保存到数据库中。
案例:在级联表中创建触发器案例
--李斯文不能删
(什么时候触发?a.delete时; b.when 条件满足时; c.代码中写明)
SQL>create or replace trigger t_studel
after delete --删除操作之后
on stuinfo
for each row
begin
if :old.stuname=\'李斯文\' then --如果:old表中存在李斯文,就提示不能删
--抛出异常
raise_application_error(-20010,\'该学生不能删!!!\');
end if;
end;
SQL>delete from emp;
--李斯文不能删也不能改
只需修改上例代码中的:
……
after delete or update
……
--怎么知道是(insert\\delete\\update)哪个操作?不知道没关系,用case when语句
……
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 :new.stuname=\'张杨\' then
raise_application_error(-20012,\'该学生你也敢招!!!\');
end if;
end case;
end;
6.多表连接触发器
在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=\'李斯文\';
7. 触发器的应用(标识列):
标识列:序列+触发器
--解决:
(1)建表
create table tb_715(
sid number,
sname varchar2(22)
)
(2)创建序列
create sequence seq715;
(3)创建个触发器,用前触发,用new表
create or replace trigger t_insert
before insert
on tb_715
for each row
begin
--新表中的id=序列的下一个值
:new.sid:=seq715.nextval;
end;
*****************************************
oracle 11g的语法:
:new.sid:=seq715.nextval;
oracle 10g的语法:
select seq715.nextval into :new.sid from dual;
别用变量,用变量的方法就是11g的写法。
Oracle触发器分:前触发、后触发
以上是关于触发器详解的主要内容,如果未能解决你的问题,请参考以下文章