zoukankan      html  css  js  c++  java
  • Oracle--触发器

    触发器

        特殊的存储过程, 不需要我们手动调用, 当用户触发某一个行为, Oracle自动执行相对于的触发器

    触发器的语法: trigger

    CREATE [OR REPLACE] TRIGGER 触发器名 触发时间 触发事件
    [ON表名/视图名]
    [FOR EACH ROW] [when 条件] //加上FOR EACH ROW 即为行级触发器,不加时为语句级触发器
    DECLARE
      声明部分
    BEGIN
      pl/sql语句
    END;

    注意:

    --  1)  触发时间:即该触发器是在触发事件发生之前(BEFORE)还是之后(AFTER)触发, instead of替换,只用于视图 ,用的很少.
    --  2) 触发事件: 某个动作:   可以写多个
    --      DML触发: insert, update,delete     ***
    --      DDL触发: cretae  alter   drop      ***
    --      系统事件: oracle服务系统的启动, 关闭,异常
    --      用户事件: 登录, 退出
    
    --  3)触发条件:由WHEN子句指定一个逻辑表达式。只有当该表达式的值为TRUE时,遇到触发事件才会自动执行触发操作。
    
    --  4) 触发频率: FOR EACH ROW: 行级触发, 操作每一行,都触发,  没有加: 语义级触发, 只触发一次

    注意: 在oracle规定: 在触发器中不能提交(commit)/回滚(rollback)事务
      原因:oracle把触发器当成后台监控,而我们的commit/rollback是前台监控
      所以你不能用后台来操控前台的操作.

    语义级触发器:例:

    -- 编写一个针对于emp_back3 进行删除操作的触发器
    create  or replace  trigger  trig_deleteEmp after  delete
    on emp_back3
    declare
    begin
       dbms_output.put_line('删除了数据');
    end;
      --执行
      --删除
      delete emp_back3 where deptno = 20;

    行级触发器:例:

    --行级触发器  for each row
    create  or replace  trigger  trig_deleteEmp after  delete
    on emp_back3
    for each row 
    declare
    begin
       dbms_output.put_line('删除了数据');
    end;
    drop  trigger trig_deleteEmp;
       --执行
      --删除
      delete emp_back3 where deptno = 20;

    触发器的一些操作

      --查看当前用户创建哪些触发器
      select * from user_triggers;
      
      --查看某个触发器的源代码
      select * from user_source where name ='TRIG_EMP2_UPDATE';
      
      --禁用触发器 alter trigger 触发器名 disable
      alter trigger TRIG_EMP2_UPDATE disable;
      
      --启动触发器 alter trigger 触发器名 enable
      alter trigger TRIG_EMP2_UPDATE enable;
      
      --启动某张表中定义所有的触发器
      alter table emp2 enable all triggers;
      --禁用某张表中定义的所有触发器
      alter table emp2 disable all triggers;
      
      --删除触发器
      drop trigger TRIG_EMP2_UPDATE;

    触发器的谓词

    inserting, deleting, updating
    --如果一个触发绑定多个事件,    想知道 触发这个触发器由哪个事件触发
    --通过谓词来判断,  
    --如果是insert事件触发, inserting谓词的值为true
    --如果是delete事件触发, deleting谓词的值为true --如果是update事件触发, updating谓词的值为true

    例:

    create or replace  trigger  trig1 after insert or delete or update
    on emp_back3
    declare
    begin
      if  inserting  then
      --如果是插入, 打印  insert table
       dbms_output.put_line(' insert table');   -- 调用dbms_output包下的put_line() 存储过程
      elsif deleting then 
      --如果是删除, 打印  delete table
      dbms_output.put_line(' delete table');
      elsif updating then
      --如果是修改, 打印  update table
       dbms_output.put_line(' update table');
      end if;
    end;
    
    insert into emp_back3  values(1010,'JIM','ANALYST',7566,sysdate,4500,null,20);
    
    delete from emp_back3 where  empno = 1010;
    
    update emp_back3 set sal = sal + 2;

    伪记录

     :new  新的记录,     :old 旧的记录   ***伪记录 只能在行级触发器有效
    -- insert操作:  只有  :new 
    -- delete操作: 只有  :old
    -- update操作:  有:new   :old

    例: 加薪, 不能加倒薪,   抛异常(自定义错误异常),  oracle 会捕获的 

    create or replace trigger trig2  after  update
    on emp_back3
    for each row
    --when 条件
    declare
    begin
       if :old.sal > :new.sal   then
          -- 学习oracle提供的一种抛异常的方式:  这个异常会被Oracle进行捕获
          -- 自定义的错误代码:  -20000~-20999
          -- raise_application_error(错误代码, 错误信息); 
          raise_application_error(-20001,'不能加倒薪');
       end if;
    end;
    -- 执行
    begin
      update emp_back3 set sal = sal - 1 where empno = 1001;
      commit;
      exception
         when others then
          dbms_output.put_line('出错了...');
          rollback;
    end;

    触发器的条件when

    /*
    在Oracle触发器中,可以使用when关键字来指定触发器触发的条件,条件触发器不仅仅要满足触发事件,而且还有满足触发条件.
        注意:
    1.when 只能在行级触发器中使用.
    2.when中使用伪记录(new,old)时不需要加:
    */

    例:

    --只有更新后的工资大于更新前的薪水 ,则打印update add
     create or replace trigger trig_emp
      after update on emp_back3
      for each row
      --更新后的工资大于更新前的薪水,when中伪记录不需要加 :
      when (new.sal >old.sal )
      begin
          dbms_output.put_line('update ok');
      end;
    --修改
      update emp_back3 set sal = sal + 1 where empno = 1001;

    DDL触发器

    -- 语法:
     create [or replace ] trigger 触发器名
       {before/after}
        {create/drop/alter}--触发事件可以多个
     on database --注意此时的触发不再对某张表的数据
     [when 条件]
     declare
          
     begin
                  --执行语句
     end

    读取DDL事件属性
        sysevent -->事件
        dictionary_obj_type :-->对象类型,如表
        dictionary_obj_name -->对象名称:如表名
        dictionary_obj_owner -->拥有者
        user --> 获取当前登录的用户名

    触发器 对数据库所有的用户都有效
      是system用户创建

    例:创建一个日志表

     create or replace trigger trig_logRecode after
     create or alter or drop
     on database
     declare
        --创建变量来接收
        v_action varchar2(50);
        v_type varchar2(50);
        v_name varchar2(50);
     begin
         --给变量赋值
         v_action := sysevent;
         v_type := dictionary_obj_type;
         v_name := dictionary_obj_name;
         
         --往 tb_recode 插入数据
         insert into tb_record values(seq_record_id.nextval,user,v_type,v_name ,v_action,default);
         --触发器,自动提交, 不能手动提交
        dbms_output.put_line('日志添加成功!!');
     end;
     
     -- tb_record  在system用户下
     select *  from tb_record;

    用户事件:

     -- 用户登录退出日志表
    create table userlog (  
                 username varchar2(20),   
                 logon_time date
    ); 
    
    --logon登录操作
    create or replace trigger database_logon   
      after logon   on database  --登录数据库后触发
      begin  
         insert into userlog    
         values(user,sysdate);   
        -- commit;
      end;  
    --执行
    select *  from userlog;

     例题:  禁止在非工作时间(工作时间:星期一到星期五的9:00到18:00)往emp表插入数据

    create or replace trigger tirg_insertWork after insert
    on empcopy
    for each row
    declare
      week varchar2(10);
      hours number;
    begin
      select to_char(sysdate, 'day'),to_char(sysdate, 'hh24') into week,hours from dual;
       if week in('星期六','星期天') or hours not between 9 and 18   then
         raise_application_error(-20001,'禁止在非工作时间插入数据');
       else
         dbms_output.put_line('插入成功!!');
       end if;
    end;
    -- 执行
    declare
    begin
    insert into empcopy values('1234','james','CLERK','7902',sysdate,'2000',null,10);
      exception
      when others then
      dbms_output.put_line('插入失败,禁止在非工作时间插入数据!!');
    end;
    View Code
  • 相关阅读:
    ID3决策树---Java
    Static、final、abstract、接口、构造方法及java语法总结
    集合类 Collection
    String、StringBuilder
    java基础类:Object类和Math类
    如何快速定位TempDB产生问题
    教你实现图片的惰性加载
    如何在 apache 中开启 gzip 压缩服务
    Data URI 应用场景小结
    获取图片base64编码的几种方法
  • 原文地址:https://www.cnblogs.com/64Byte/p/12746358.html
Copyright © 2011-2022 走看看