触发器: 当满足触发器条件,则系统自动执行触发器的触发体。 触发时间:有 before,after.触发事件:有 insert,update,delete 三种。触发类型:有行触发、语句触发。
before:先执行,再操作
after: 先操作,再执行。
当执行insert的时候, :new存在 ,:old没有
当执行delete的时候, :new不存在,:old存在
当执行update的时候, :new存在,:old存在
1.创建触发器
--创建插入或者是修改触发器trig1
create or replace trigger tirg1
before insert or update on 成绩表 for each row
--加上了for each row 就是行级别,没有就是表级别
begin
dbms_output.put_line('触发器trig1响应了')
end;
set serverout on --打开触发器响应
insert into 成绩表 values(5,'A',50); --数据插入之后,显示触发器trig1响应了
2.触发器的应用一:当用户插入记录到student表时,不能插入sno是负值的记录
create or replace trigger trig2
before insert on student for each row
begin
if :new.sno < 0 then
--rollback;--回滚不能出现在触发器中
raise_application_error(-20000,'学号错误,不能是负值!');
end if;
end;
总结:触发器中不能使用rollback,commit,create,drop,alter,saveopint等。
如果触发器的plSQL内使用:new :old,就必须是行级触发器,for each row 必须存在。
update student set sage = 41 where sno = 1;
sno sname sage
1 tom 21
先把1 tom 21记录删除,然后再把1 tom 41记录加到表里面去。
3.触发器的应用二:当用户插入记录到student表时,如果插入sno是负值,那么把sno改为相反数,再插入
create or replace trigger trig3
before insert on student for each row
begin
if :new.sno < 0 then --如果学号为负
:new.sno :=- :new.sno
end if;
end;
4.触发器修改视图
--把姓名为Kite的人住址改为安阳
update view_stu_add set zz='安阳' where sname='Kite';--更新不了
create or replace trigger tri_view
instead of update on view_stu_add for each row
declare
s_no number :=0;
begin
--从student表取得姓名,得到sno(学号)赋值给s_no
select sno into s_no from student where sname =:old.sname;
delete address where sno = s_no;--删除address表中sno为s_no的记录
insert into address values(s_no,:new.zz);--然后再插入记录 (学号,地址)
end;
update view_stu_add set zz='安阳' where sname = 'Kite'; --更新成功
--这个触发器其实就是更新address表。
5.触发器记录表操作(增删改),当用户对成绩表进行操作时,把情况记录下来。
create or replace trigger trig5
before insert or update or delete on 成绩表 for each row
begin
if inserting then --inserting 表示插入
dbms_output.put_line('插入的学生学号是:'||:new.code||',名称是:'
||:new.name||',成绩是:'||:new.score);
end if;
if updating then
dbms_output.put_line('原始记录的学生的学号是:'||:old.code||',名称是:'
||:old.name||',成绩是:'||:old.score||'。新的学生学号是:'||:new.code||'名称是:'
||:new.name||',成绩是:'||:new.score);
end if;
if deleting then
dbms_output.put_line('删除的学生学号是:'||:old.code||',名称是:'
||:old.name||',成绩是:'||:old.score);
end if;
end;
update 成绩表 set score =100 where code = 1;
--其实可以把记录保持到表里面,而且还能够显示时间,这样就可以随时掌握用户对表的操作情况。
6.数据库启动关闭时,利用触发器把记录保持到表里
create table event_table(
event varchar2(30),
time date
)
create or replace trigger tr_startup
after startup on database --数据库启动,是启动之后才能记录,所以用after
begin
insert into event_table values(ora_sysevent,sysdate);
end;
--数据库关闭
create or replace trigger tr_shutdown
before shutdown on database --关闭之前记录的,所以用before
begin
insert into event_table(ora_sysevent,sysdate);
end;
shutdown immediate --关闭数据库
startup --启动数据库
select event,to_char(time,'yyyymmdd hh2:mi:ss') from event_table;
7. 用户登录退出触发器
--用户登录触发器
create or replace trigger tr_logon
after logon on database --用户登录是登录之后才能记录
before
insert into log_table(username,logon_time,address)
values(ora_login_user,sysdate,ora_client_ip_address);
end;
--用户退出触发器
create or replace trigger tr_logoff
before logon on database --用户退出是退出之前才能记录
before
insert into log_table(username,logoff_time,address)
values(ora_login_user,sysdate,ora_client_ip_address);
end;