• Oracle的触发器Trigger


    参考:https://blog.csdn.net/weixin_41649106/article/details/86981325
    https://blog.csdn.net/htj10/article/details/114629358
    Oracle 触发器详解(trigger)

    触发器的应用场景

    1. 复杂的安全性检查
    2. 数据的确认
    3. 数据库审计
    4. 数据的备份和审计

    触发器例子1:update 之前进行安全检查

    准备工作:

    create table t_salary(id number(8), sal number(10,2));
    insert  into t_salary(id, sal) values(1, 8000);
    select * from t_salary;
    

     创建触发器:

    /**
    涨后的薪水不能低于涨前的薪水
    1 :old 和 :new 代表同一条记录
    2 :old 代表操作该行之前,这一行的值
     :new 代表操作该行之后,这一行的值
    */
    create or replace trigger checkSalary
     before update
     on t_salary
     for each row
    declare
     -- local variables here 没有变量声明的话,declare可以省略
    begin
     -- if 涨后的薪水 < 涨前的薪水 then 如何表示呢 ?
     if :new.sal < :old.sal then
       raise_application_error(-20002,'涨后的薪水:'|| :new.sal ||'小于涨前的薪水:'||:old.sal);
     end if;
    end checkSalary;
    

     测试:

    SQL> update t_salary set sal=7000 where id=1;
    update t_salary set sal=7000 where id=1
           *
    第 1 行出现错误:
    ORA-20002: 涨后的薪水:7000小于涨前的薪水:9000
    ORA-06512: 在 "SCOTT.CHECKSALARY", line 6
    ORA-04088: 触发器 'SCOTT.CHECKSALARY' 执行过程中出错
    

     删除触发器

    --删除 触发器
    drop trigger checkSalary;
    

     例子2:备份数据

    /*
    删除前,将数据备份
    */
    create or replace trigger tri_sal_delete_bk
      before delete
      on t_salary
      for each row
    begin
      insert into t_salary_del(id,sal) values(:old.id, :old.sal);
      -- commit; -- 注意不可以有提交,会报错ora-04092
    end tri_sal_delete_bk;
    

     注意:DML(delete/update/insert)触发器中不能使用DDL(CREATE,DROP,ALTER)语句,也不能使用事务控制语句(ROLLBACK, COMMIT,SAVEPOINT)。特别注意的是,在触发器的主体中引用的函数(function)/过程(procedure)中也不能有事物控制语句。

    例子3:非工作时间禁止插入数据

    /**
    非工作时间(星期六 星期日, 非9点~18点的区间)禁止写入数据
    首先要搞清楚: 触发器的类型--语句级触发器。
    不管插入了多少条数据,没有必要对每一行数据都进行校验,只要不在这个时间段内,都不让插入。
    */
    
    create or replace trigger tri_addSalaryCheck
      before insert on t_salary
    declare
     -- local variables here
    begin
      if to_char(sysdate, 'day') in ('星期六', '星期日') or
          to_number(to_char(sysdate, 'hh24')) not between 9 and 18    then
          -- 禁止insert
          raise_application_error(-20001,'非工作时间禁止插入数据');
      end if;
    end tri_addSalaryCheck;
    

    例子4:Oracle实现像Mysql的自动增长auto_increment

    -- 建表:
    CREATE TABLE t_user(U_ID NUMBER(8), UNAME VARCHAR2(20), UPASSWORD VARCHAR2(20));
    
    -- 建立序列:
    CREATE SEQUENCE SEQ_TUSER  
    INCREMENT BY 1
    MINVALUE 1                      --最小值  
    MAXVALUE 99999999               --最大值由NUMBER(8)  
    NOCYCLE                              --不打环   
    NOCACHE                              --不缓存  
    ORDER;
    COMMIT;  
    
    -- 然后建立before的触发器:
    CREATE OR REPLACE TRIGGER TRG_ADDTUSER  
    BEFORE INSERT ON t_user
    FOR EACH ROW
    BEGIN
    SELECT SEQ_TUSER.NEXTVAL INTO :NEW.U_ID FROM DUAL;
    END TRG_ADDTUSER;
    
    -- 测试:
    INSERT INTO t_user (UNAME,UPASSWORD) VALUES ('libai','589avf');
    INSERT INTO t_user (UNAME,UPASSWORD) VALUES ('zhangsan','ko098');
    COMMIT;
    select * from t_user;
    

    例子5:插入或更新或删除 后 触发

    CREATE OR REPLACE TRIGGER trigger_table01 
    AFTER INSERT OR UPDATE OR DELETE ON table01
     FOR EACH ROW
      
    DECLARE recordNum INT;
    BEGIN
      IF (inserting OR updating) THEN
        SELECT COUNT(1) INTO recordNum FROM table02 WHERE name=:NEW.USER_NAME;
        IF (recordNum =0) THEN
          EXECUTE IMMEDIATE 'insert into table02(name) values ('''||:NEW.USER_NAME||''') ';
        END IF;
      ELSIF DELETING THEN
        EXECUTE IMMEDIATE 'delete from table02 where name = '''||:OLD.USER_NAME||''' ';
      END IF;
    END;

    常记溪亭日暮,沉醉不知归路。兴尽晚回舟,误入藕花深处。争渡,争渡,惊起一滩鸥鹭。

    昨夜雨疏风骤,浓睡不消残酒。试问卷帘人,却道海棠依旧。知否?知否?应是绿肥红瘦。
  • 相关阅读:
    表达式执行工具方法
    Mysql表创建外键报错
    JVM打印加载类的详情信息
    Shell脚本查询进程存活信息
    旋转数组的最小数字
    斐波那契数列(水题)
    用两个栈实现队列
    变态跳台阶
    跳台阶
    9*9乘法表(5种输出格式)
  • 原文地址:https://www.cnblogs.com/htj10/p/15238395.html
Copyright © 2020-2023  润新知