触发器

本节要点:

  • 什么是触发器
  • 触发器类型及创建方法
    •   触发器类型
    •   创建触发器
    •   触发器组成部分
  • 理解和应用触发器
    •   行级触发器
    •   语句级触发器
    •   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 '; 

posted @ 2017-08-16 15:32  silvan_happy  阅读(358)  评论(0编辑  收藏  举报