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

    本节要点:

    • 什么是触发器
    • 触发器类型及创建方法
      •   触发器类型
      •   创建触发器
      •   触发器组成部分
    • 理解和应用触发器
      •   行级触发器
      •   语句级触发器
      •   INSTEAD OF 触发器
      •   模式触发器
      •   启用、禁用和删除触发器

    1   什么是触发器

    触发器和存储过程比较类似,它由PL/SQL编写并存储在数据库中,它可以调用存储过程,但是触发器本身的调用和存储过程调用是不一样的。存储过程由用户、应用程序、触发器或者其他过程调用。但是触发器只能由数据库的特定事件来触发。所以,触发器是当特定事件出现时自动执行的存储过程,不能被显式调用,特定事件可以是执行更新的DML语句和DDL语句。

    触发器的作用:

    • l  自动生成数据:如序列
    • l  自定义复杂的安全权限:比如可以实现完整性规则
    • l  提供审计和日志记录
    • l  启用复杂的业务逻辑:除了基础数据变动还可以完成一些额外的操作

    2   触发器类型及创建方法

    触发器类型主要有DDL 触发器、数据库级触发器和DML触发器,其中DML触发器又可以分为语句级触发器、行级触发器和INSTEAD OF 触发器等。

    2.1  触发器类型

    • DDL 触发器:在模式中执行 DDL 语句时执行
    • 数据库级触发器:在发生打开、关闭、登录和退出数据库等系统事件时执行
    • DML 触发器:在对表或视图执行DML语句时执行
      •   语句级触发器:无论受影响的行数是多少,都只执行一次
      •   行级触发器:对DML语句修改的每个行执行一次
      •   INSTEAD OF 触发器:用于用户不能直接使用 DML 语句修改的视图

    2.2  创建触发器

    语法:

    CREATE [OR REPLACE] TRIGGER trigger_name

    AFTER | BEFORE | INSTEAD OF

    [INSERT] [[OR] UPDATE [OF column_list]]

    [[OR] DELETE]

    ON table_or_view_name

    [REFERENCING {OLD [AS] old / NEW [AS] new}]

    [FOR EACH ROW]

    [WHEN (condition)]

    pl/sql_block;

    • TRIGGER:触发器的关键词
    • AFTER | BEFORE | INSTEAD OF:触发器类型为前触发|后触发|替换类型
    • INSERT| UPDATE| DELETE:表示触发的事件
    • [OF column_list]:触发条件具体到的某列
    • ON table_or_view_name:触发器作用的表或视图
    • [FOR EACH ROW]:表示行级触发,省略则为语句级触发器
    • [WHEN (condition)]:触发该触发器的条件
    • pl/sql_block:表示触发器的函数体

    示例:为表m_user的user_pswd字段创建更新前触发的触发器,OLD.表示访问前的数据,:NEW.表示访问后的数据

    CREATE OR REPLACE TRIGGER trig_stu

      BEFORE UPDATE OF user_pswd ON m_user

      FOR EACH ROW

      WHEN (OLD.user_nm = '3')

    BEGIN

      :NEW.user_nm := '333333';

    END;

    更新语句

    update m_user t set t.user_pswd='555' where t.user_cd='7';

    2.3  触发器的组成部分

    触发器由三部分组成:

    1)       触发器语句(事件):定义激活触发器的 DML 事件和 DDL 事件

    示例:为m_user表创建trig_stu触发器

    CREATE OR REPLACE TRIGGER trig_stu

    在更新 user_pswd列之前激活触发器

    BEFORE UPDATE OF user_pswd ON m_user

    2)       触发器限制:执行触发器的条件,该条件必须为真才能激活触发器,即WHEN (condition)部分

    示例:只有在WHEN子句中的条件得到满足时,才激活trig_stu触发器

              WHEN (OLD.user_nm = '3')

    3)       触发器操作(主体):包含一些 SQL 语句和代码,它们在发出了触发器语句且触发限制的值为真时运行,即pl/sql_block部分

    示例:如果WHEN子句中的条件得到满足,将执行BEGIN 块中的代码

     :NEW.user_nm := '333333';

    3   理解和应用触发器

    3.1  行级触发器

    创建表:

    create table t_temp(f_id number,f_name varchar2(20));

    创建序列:

    create sequence seq_tempid;

    创建触发器:

    create trigger trig_temp

    /*表t_temp更新或者插入字段f_id时触发器被触发*/

      before insert or update of f_id on t_temp

      for each row

    begin

    /*如果事件“inserting”发生,则执行1号语句,否则执行2号语句,注:不包括更新*/

      if inserting then

        select seq_tempid.nextval into :New.f_id from dual;/*1号*/

      else

        Raise_Application_Error(-20020, '不允许更新ID值!');/*2号*/

      end if;

    end;

    插入数据(正常):

    insert into t_temp (f_id,f_name) values('11','name1');

    更新数据(报错):

    update t_temp set f_id='11' where f_id='1';

    删掉触发器:

    drop trigger trig_temp;

    再次更新数据(正常)。

    说明:触发器的功能起作用。

    3.2  语句级触发

    create or replace trigger trig_stu

    after insert or delete or update

    on t_student

    begin

      if inserting then

        dbms_output.put_line('已添加t_student中的数据');

      elsif deleting then

        dbms_output.put_line('已删除t_student中的数据');

      elsif updating then

        dbms_output.put_line('已更新t_student中的数据');

      end if;

    end;

    注:没有for each row,根据语句的类型来触发相应的操作。

    3.3  INSTEAD OF 触发器

    在该类型的触发器作用下,如果对作用对象执行DML操作,那么该操作会被触发器的内部操作所取代。可以用在视图当中,解决视图不可更新的问题。

    示例:对视图进行数据插入时,实际是操作其依附的真正存在的表productinfo,而productinfo表中产品类型信息是与表categroyinfo关联的,无法对视图直接进行数据插入。所以有了INSTEAD OF 触发器,在插入数据之前根据category查询出类型的编号categid,再进行数据插入。

    • 表productinfo有七个字段:productid、productname、productprice、quantity、category、desperation、origin。
    • 表categroyinfo保存了产品类型信息categroyid 和category
    • 视图productinfo_view的定义

    create view productinfo_view as

    select distinct productname, productprice, quantity, category, origin

    from productinfo

    • 创建触发器

    Create trigger instead_of_tgr

      Instead of insert on productinfo_view

    Declare

      Categid varchar2(10);

    Begin

      Select categroyid

      Into categid

      From categroyinfo

      Where categroyinfo.categroyname = :new.category;

    Insert into productinfo

    Values

    (‘0240090001’,

    :new. Productname,

    :new. productprice,

    :new. quantity,

    Categid,

    ‘test’,

    :new. Origin);

    End;

    • 对视图进行增加操作,最后productinfo中的category字段将对应categroyinfo中categroyid的编号。

    Insert into productinfo_view values(‘触发器测试’,1000,0,’雨具’,’中国’);

    3.4  模式触发器

                    也称DDL类型触发器,即因DDL操作而激发的触发器。利用模式触发器可以限制和记录特定的DDL操作。

    示例:创建一个表和模式触发器,通过触发器将删除表的日志记录到表中

    创建日志表:create table t_droppedobj

              (

                f_objname varchar2(20),

                f_objtype varchar2(20),

                f_dropdate date

              );

    创建触发器:create or replace trigger trig_dropobj

               after drop on schema

               begin

                 insert into t_droppedobj values

                 (Ora_Dict_Obj_Name,Ora_Dict_Obj_Type,Sysdate);

               end;

    3.5  启用、禁用和删除触发器

    1)  启用触发器

     ALTER TRIGGER trig_stu ENABLE;

    2)  禁用触发器

    ALTER TRIGGER trig_stu DISABLE;

    3)  删除触发器

    DROP TRIGGER trig_stu;

    4)  查看有关触发器的信息:USER_TRIGGERS 数据字典视图包含有关触发器的信息

    根据表名称查询触发器信息:

    SELECT TRIGGER_NAME FROM USER_TRIGGERS

    WHERE TABLE_NAME=‘M_USER '; /*注意表名称要大写*/

    根据触发器名称查询触发器信息:

    SELECT TRIGGER_TYPE, TRIGGERING_EVENT, WHEN_CLAUSE

    FROM USER_TRIGGERS

    WHERE TRIGGER_NAME = ‘TRIG_TEMP '; 

  • 相关阅读:
    Lintcode415-Valid Palindrome-Medium
    Lintcode455-StudentID-Easy
    Lintcode241-String to Integer
    Lintcode521-Remove Duplicate Numbers in Array-Easy
    Lintcode214-Max of Array-Naive
    面试一个小公司,TPM相关概念
    C#, introduction, general
    make命令和makefile
    OS_Architecture_MemoryHierarchy
    Leecode_98_Validate_Binary_Search_Tree
  • 原文地址:https://www.cnblogs.com/zhouyeqin/p/7373614.html
Copyright © 2011-2022 走看看