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);

image

示例: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;-- 未触发

image

表级触发器与行级触发器

先准备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;
image

无论修改多少行,触发器只执行一次。
原因:默认是语句级触发器,作用于表,只执行一次。

a.语句级触发器
作用于表,只触发一次
b.行级触发器
作用于每一行,每满足一次条件都执行一次;可以执行多次触发器
for each row[when条件]

修改update触发器 添加for each row 后,再试一次
image

打印 修改前后的值(: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;
image

触发器应用

示例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…)

posted @ 2022-07-16 11:29  姬雨晨  阅读(733)  评论(0编辑  收藏  举报