plsql-触发器
触发器简介
每当对一个表执行一个DML时,Oracle就会自动调用相应的触发器(一段PL/SQL代码)。
语法:
create [or replace] trigger 触发器名
before|after
delete|insert|update [of 列名]
on 表名
for each row [when 条件]
plsql代码
/
示例:insert
创建学生表
CREATE TABLE student
(
stuno NUMBER,
stuname VARCHAR(20),
stuage NUMBER
);
创建触发器:每当成功插入新学生后,自动打印“增加成功”
create trigger logNowStudent
after insert
on student
declare
begin
dbms_output.put_line('增加成功');
end;
/
测试:
sqlplus或sql developer都必须set SERVEROUTPUT ON
;
insert into student values (1,'zs',1);
示例:update of 列名
create TRIGGER logUpdateStudent
after update of stuage
on student
declare
begin
dbms_output.put_line('年龄修改成功');
end;
/
测试
update student set stuage =18 where stuno =1;-- 触发
update student set stuname = 'ls' where stuno=1;-- 未触发
表级触发器与行级触发器
先准备9条数据,每次插入都会触发一下insert触发器
insert into student values (2,'zs2',2);
insert into student values (3,'zs3',3);
insert into student values (4,'zs4',4);
insert into student values (5,'zs5',5);
insert into student values (6,'zs6',6);
insert into student values (7,'zs7',7);
insert into student values (8,'zs8',8);
insert into student values (9,'zs9',9);
然后 修改一下,同时修改了三条数据,但update触发器 只 触发了一次
update student set stuage=18 where stuno <4;
无论修改多少行,触发器只执行一次。
原因:默认是语句级触发器,作用于表,只执行一次。
a.语句级触发器
作用于表,只触发一次
b.行级触发器
作用于每一行,每满足一次条件都执行一次;可以执行多次触发器
for each row[when条件]
修改update触发器 添加for each row 后,再试一次
打印 修改前后的值(:old、:new识别值状态)
行级触发器中有两个伪变量,用于识别值的状态
:old 操作之前,是记录变量,使用形式::old.字段名
:new 操作之后,是记录变量,使用形式::new.字段名
只在DML触发表中字段时才有效,只能在触发器内部使用
create or replace TRIGGER logUpdateStudent
after update of stuage
on student
for each row
declare
begin
dbms_output.put_line('年龄修改成功' || :old.stuage || :new.stuage);
end;
测试sql
update student set stuage=18 where stuno >6;
触发器应用
示例1:
/*
复杂的安全性检查
禁止在非工作时间插入新员工
1. 周末:to_char(sysdate,'day') in ('星期六','星期日')
2. 上班前 下班后:to_number(to_char(sysdate,'hh24')) not between 9 and 18
*/
create or replace trigger securityemp
before insert
on emp
begin
if to_char(sysdate,'day') in ('星期六','星期日') or
to_number(to_char(sysdate,'hh24')) not between 9 and 18 then
--禁止插入
raise_application_error(-20001,'禁止在非工作时间插入新员工');
end if;
end;
/
示例2:
/*
数据确认
涨后的薪水不能少于涨前的薪水
*/
create or replace trigger checksalary
before update
on emp
for each row
begin
--if 涨后的薪水 < 涨前的薪水 then
if :new.sal < :old.sal then
raise_application_error(-20002,'涨后的薪水不能少于涨前的薪水.涨前:'||:old.sal||' 涨后:'||:new.sal);
end if;
end;
/
练习题:限制每个部门只招5个员工。(insert into…)