源码-Oracle数据库管理-第十五章-触发器和游标-Part 1(理解触发器)

纸上得来终觉浅,绝知此事要躬行。

--15.1.2 定义触发器
--15.1.3 触发器的分类
--15.2 DML触发器
--15.2.1 触发器的执行顺序
--1. 单行触发器的执行顺序
--2. 多行触发器执行顺序
--15.2.2 定义DML触发器
--创建一个emp_log表来记录对emp表的变更
create table emp_log2(
log_id number,
log_action varchar2(100),
log_date date,
empno number(4),
ename varchar2(10),
job varchar2(18),
mgr number(4),
hiredate date,
sal number(7,2),
comm number(7,2),
deptno number(2));

--代码15.2 记录日志触发器示例
--创建一个emp_log表用来记录对emp表的更改
CREATE TABLE emp_log(
   log_id NUMBER,               --日志自增长字段
   log_action VARCHAR2(100),    --表更改行为,比如新增或删除或更改 
   log_date DATE,                --日志日期
   empno NUMBER(4),            --员工编号
   ename VARCHAR2(10),         --员工名称
   job VARCHAR2(18),            --职别
   mgr NUMBER(4),               --管理者
   hiredate DATE,                 --雇佣日期 
   sal NUMBER(7,2),              --工资
   comm NUMBER(7,2),           --提成或分红
   deptno NUMBER(2)             --部门编号
);

drop table emp_log;

--创建一个AFTER行触发器
CREATE OR REPLACE TRIGGER t_emp_log
   AFTER INSERT OR DELETE OR UPDATE ON emp  --触发器作用的表对象以及触发的条件和触发的动作
   FOR EACH ROW                                 --行级别的触发器
BEGIN
   IF INSERTING THEN                              --判断是否是INSERT语句触发的
      INSERT INTO emp_log                         --向emp_log表中插入日志记录
      VALUES(
        emp_seq.NEXTVAL,
        'INSERT',SYSDATE,
        :new.empno,:new.ename,:new.job,
        :new.mgr,:new.hiredate,:new.sal,
        :new.comm,:new.deptno );
   ELSIF UPDATING THEN                          --判断是否是UPDATE语句触发的
      INSERT INTO emp_log                         --首先插入旧的记录
      VALUES(
        emp_seq.NEXTVAL,
        ' UPDATE_NEW',SYSDATE,
        :new.empno,:new.ename,:new.job,
        :new.mgr,:new.hiredate,:new.sal,
        :new.comm,:new.deptno );  
      INSERT INTO emp_log                        --然后插入新的记录
      VALUES(
        emp_seq.CURRVAL,
        ' UPDATE_OLD',SYSDATE,
        :old.empno,:old.ename,:old.job,
        :old.mgr,:old.hiredate,:old.sal,
        :old.comm,:old.deptno );              
   ELSIF DELETING THEN                         --如果是删除记录
      INSERT INTO emp_log
      VALUES(
        emp_seq.NEXTVAL,
        'DELETE',SYSDATE,
        :old.empno,:old.ename,:old.job,
        :old.mgr,:old.hiredate,:old.sal,
        :old.comm,:old.deptno );         
   END IF;
END;

select * from emp_log;
insert into emp values(7777,'李四友','职员',null,sysdate, 2000, 400, 20);
select * from emp;
update emp set sal=5000 where empno=7777;
drop trigger log_sal_adj;
delete from emp where empno=7777;


--15.2.3 使用条件谓词
--代码15.3 使用条件谓词
CREATE OR REPLACE TRIGGER t_condition_demo
  BEFORE                            --指定BEFORE触发器
    INSERT OR                       --监控INSERT语句
    UPDATE OF sal, deptno OR        --仅监控对sal和deptno列的更新
    DELETE                          --监控DELETE语句
  ON emp                            --触发的对象
BEGIN
  CASE
    WHEN INSERTING THEN             --使用INSERTING谓词判断
      DBMS_OUTPUT.PUT_LINE('插入了一条记录');
    WHEN UPDATING('sal') THEN       --使用UPDATING谓词判断
      DBMS_OUTPUT.PUT_LINE('更新了sal字段');
    WHEN UPDATING('deptno') THEN
      DBMS_OUTPUT.PUT_LINE('更新了deptno字段');
    WHEN DELETING THEN              --使用DELETING谓词进行判断
      DBMS_OUTPUT.PUT_LINE('删除了一条记录');
  END CASE;
END;


--15.2.4 使用old和new伪记录
--代码15.4 创建用于数据同步的表
CREATE TABLE emp_data         --保存员工记录数据的测试表
( 
    emp_id INT,                   --自增长字段
    empno NUMBER,              --员工编号
    ename VARCHAR2(20)         --员工名称
);
CREATE TABLE emp_data_his      --保存员工记录数据的历史备份表
( 
    emp_id INT,                   --自增长字段
    empno NUMBER,              --员工编号
    ename VARCHAR2(20)         --员工名称
);

drop table emp_data_his;

--代码15.5 创建t_emp_data触发器
CREATE OR REPLACE TRIGGER t_emp_data
   BEFORE INSERT
   ON emp_data                               --触发器作用的表对象以及触发的条件和触发的动作
   FOR EACH ROW                            --行级别的触发器
DECLARE
   emp_rec   emp_data%ROWTYPE;
BEGIN
  SELECT emp_seq.NEXTVAL INTO :NEW.emp_id FROM DUAL; --对BEFORE触发器的NEW赋值
   --emp_rec:=:new;                            --不能直接对谓词记录进行记录级别的操作
   emp_rec.emp_id := :NEW.emp_id;
   emp_rec.empno := :NEW.empno;
   emp_rec.ename := :NEW.ename;
   INSERT INTO emp_data_his VALUES emp_rec; --使用记录级别的操作
   IF :OLD.emp_id IS NULL THEN               --在INSERT操作中:OLD伪记录成员的值都是NULL
      DBMS_OUTPUT.put_line('INSERT操作不包含:OLD伪记录的值');
    END IF;
END;



insert into emp_data (empno,ename) values (8888,'发财');
select * from emp_data;
select * from emp_data_his;

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值