知识点一、触发器(trigger)
  推荐练习文档:
  http://wenku.baidu.com/link?url=brtd9myO4XIaEjRPaRB0yWgV2_TfXmNxS6KKjB_avq7d0hPs3SknJdrs-JLtWe–H-f3q-I61HUxkcqqAFMC0z6Zf65QBbmFRB8TAlULmGS
  http://www.cnblogs.com/friends-wf/p/3793417.html存储过程练习
  http://blog.csdn.net/indexman/article/details/8023740/(推荐博客触发器)(强烈推荐!!!)
  触发器会被编译且存储在数据库服务器中。由一个事件来启动运行,即触发器是当某个事件发生时自动隐式运行。并且触发器不能接收参数。所以运行触发器叫触发或点火。oracle事件指的是对数据库的表进行insert、update及delete操作或对视图进行类似的操作。oracle将触发器的功能扩展到了触发oracle,如数据库的启动和关闭等。所以触发器常用来完成由数据库的完整性约束难以完成的复杂业务规则的约束,或用来监视对数据库的各种操作,实现审计功能。
  创建触发器
  create [or replace] trigger 触发器名
  before|after|instead of 某个事件 on 表名|视图名|database|用户名.schema
  [for each row [when]]
  PL/SQL块|调用过程(call procedure_name)
  or replace:如果数据库已经存在同名的触发器,则替换
  before|after:指定触发时间点
  instead of:替换视图操作,只能为行级触发器
  某个事件:指定当发生什么操作的时候,触发触发器
  on:指定基于什么创建触发器
  for each row [when]:表示改变每行数据时,执行一次触发器
  PL/SQL块|调用过程(call procedure_name):触发器执行时,执行的代码
  触发器分类:
  关于触发器先前介绍:
  before触发器:在触发语句运行前先运行触发动作
  create [or replace] trigger 触发器名
  before insert|delete|update on 表名
  before create|drop|alter on database|用户名.schema
  [for each row [when]]
  PL/SQL块|调用过程(call procedure_name)
  行级触发器:当某触发事件发生时,对受到该操作影响的每一行数据,触发器都单独执行一次。指定了for each row选项。
  create [or replace] trigger 触发器名
  before|after|instead of insert|delete|update on 表名|视图名
  for each row [when]
  PL/SQL块|调用过程(call procedure_name)
  在行级触发器的PL/SQL块和when子句中可以使用相关名称参照当前的新、旧列值,默认的相关名称分别为new、old。触发器的PL/SQL块中应用相关名称时,必须在它们之前加冒号(:),但在when子句中则不加冒号。
  触发器在数据库里以独立的对象存储,它与存储过程和函数不同的是,存储过程与函数需要用户显示调用才执行,而触发器是由一个事件来启动运行。即触发器是当某个事件发生时自动地隐式运行。并且,触发器不能接收参数。所以运行触发器叫触发或点火(firing)。ORACLE事件指的是对数据库的表进行的INSERT、UPDATE及DELETE操作或对视图进行类似的操作。ORACLE将触发器的功能扩展到了触发ORACLE,如数据库的启动与关闭等。所以触发器常用来完成由数据库的完整性约束难以完成的复杂业务规则的约束,或用来监视对数据库的各种操作,实现审计的功能。
  1 DML触发器
  ORACLE可以在DML语句进行触发,可以在DML操作前或操作后进行触发,并且可以对每个行或语句操作上进行触发。
  2 替代触发器
  由于在ORACLE里,不能直接对由两个以上的表建立的视图进行操作。所以给出了替代触发器。它是ORACLE 8专门为进行视图操作的一种处理方法。
  3 系统触发器
  ORACLE 8i 提供了第三种类型的触发器叫系统触发器。它可以在ORACLE数据库系统的事件中进行触发,如ORACLE系统的启动与关闭等。
  语句级触发器:当某触发事件发生时,该触发器只执行一次。未指定for each row选项。
  create [or replace] trigger 触发器名
  before|after insert|delete|update on 表名|视图名
  before|after create|drop|alter on database|用户名.schema
  PL/SQL块|调用过程(call procedure_name)
  行级触发器:行级触发器对DML语句影响的每个行执行一次。
  语句级触发器对每个DML语句执行一次,如果在TABLE表中插入的数据为500行,那么这个表上的语句级触发器只执行一次,而行级的触发器要执行500次了。 
  是指为受到影响的各个行激活的触发器,定义与语句级触发器类似,但是要注意下面两个不同点:
  1、 定义语句中包含FOR EACH ROW子句   www.2cto.com 
  2、 在BEFORE……FOR EACH ROW触发器中,用户可以引用受到影响的行值。 
  DML触发器
  创建DML触发器
  触发器名与过程名和包的名字不一样,它是单独的名字空间,因而触发器名可以和表或过程有相同的名字,但在一个模式中触发器名不能相同。
  DML触发器的限制
  l         CREATE TRIGGER语句文本的字符长度不能超过32KB;
  l         触发器体内的SELECT 语句只能为SELECT … INTO …结构,或者为定义游标所使用的SELECT 语句。
  l         触发器中不能使用数据库事务控制语句 COMMIT; ROLLBACK, SVAEPOINT 语句;
  l         由触发器所调用的过程或函数也不能使用数据库事务控制语句;
  l         触发器中不能使用LONG, LONG RAW 类型;
  l         触发器内可以参照LOB 类型列的列值,但不能通过 :NEW 修改LOB列中的数据;
  DML触发器基本要点
  l         触发时机:指定触发器的触发时间。如果指定为BEFORE,则表示在执行DML操作之前触发,以便防止某些错误操作发生或实现某些业务规则;如果指定为AFTER,则表示在执行DML操作之后触发,以便记录该操作或做某些事后处理。
  l         触发事件:引起触发器被触发的事件,即DML操作(INSERT、UPDATE、DELETE)。既可以是单个触发事件,也可以是多个触发事件的组合(只能使用OR逻辑组合,不能使用AND逻辑组合)。
  l         条件谓词:当在触发器中包含多个触发事件(INSERT、UPDATE、DELETE)的组合时,为了分别针对不同的事件进行不同的处理,需要使用ORACLE提供的如下条件谓词。
  1)。INSERTING:当触发事件是INSERT时,取值为TRUE,否则为FALSE。
  2)。UPDATING [(column_1,column_2,…,column_x)]:当触发事件是UPDATE      时,如果修改了column_x列,则取值为TRUE,否则为FALSE。其中column_x是可选的。
  3)。DELETING:当触发事件是DELETE时,则取值为TRUE,否则为FALSE。
  解发对象:指定触发器是创建在哪个表、视图上。
  l         触发类型:是语句级还是行级触发器。
  l         触发条件:由WHEN子句指定一个逻辑表达式,只允许在行级触发器上指定触发条件,指定UPDATING后面的列的列表。
  instead of 触发器:用于对视图的DML触发,由于视图有可能是多个表进行联接而成,因而并非所有视图都是可更新的。但可以按照所需的方式执行更新。
  create [or replace] trigger 触发器名
  instead of insert|delete|update on 视图名
  [for each row [when]]
  PL/SQL块|调用过程(call procedure_name)
  只能创建在视图上,并且该视图没有指定with check option选项;
  for each row子句是可选的,即instead of触发器只能在行级上触发、或只能是行级触发器,
  没有必要指定;
  没有必要在针对一个表的视图上创建instead of触发器,只要创建DML触发器可以了。   
  触发器组成:
  l         触发事件:引起触发器被触发的事件。 例如:DML语句(INSERT, UPDATE, DELETE语句对表或视图执行数据处理操作)、DDL语句(如CREATE、ALTER、DROP语句在数据库中创建、修改、删除模式对象)、数据库系统事件(如系统启动或退出、异常错误)、用户事件(如登录或退出数据库)。
  l         触发时间:即该TRIGGER 是在触发事件发生之前(BEFORE)还是之后(AFTER)触发,也是触发事件和该TRIGGER 的操作顺序。
  l         触发操作:即该TRIGGER 被触发之后的目的和意图,正是触发器本身要做的事情。 例如:PL/SQL 块。
  l         触发对象:包括表、视图、模式、数据库。只有在这些对象上发生了符合触发条件的触发事件,才会执行触发操作。
  l         触发条件:由WHEN子句指定一个逻辑表达式。只有当该表达式的值为TRUE时,遇到触发事件才会自动执行触发器,使其执行触发操作。
  l         触发频率:说明触发器内定义的动作被执行的次数。即语句级(STATEMENT)触发器和行级(ROW)触发器。
  语句级(STATEMENT)触发器:是指当某触发事件发生时,该触发器只执行一次;
  行级(ROW)触发器:是指当某触发事件发生时,对受到该操作影响的每一行数据,触发器都单独执行一次。
  编写触发器时,需要注意以下几点:
  l         触发器不接受参数。
  l         一个表上多可有12个触发器,但同一时间、同一事件、同一类型的触发器只能有一个。并各触发器之间不能有矛盾。
  l         在一个表上的触发器越多,对在该表上的DML操作的性能影响越大。
  l        触发器大为32KB。若确实需要,可以先建立过程,然后在触发器中用CALL语句进行调用。
  l         在触发器的执行部分只能用DML语句(SELECT、INSERT、UPDATE、DELETE),不能使用DDL语句(CREATE、ALTER、DROP)。
  l         触发器中不能包含事务控制语句(COMMIT,ROLLBACK,SAVEPOINT)。因为触发器是触发语句的一部分,触发语句被提交、回退时,触发器也被提交、回退了。
  l         在触发器主体中调用的任何过程、函数,都不能使用事务控制语句。
  l         在触发器主体中不能申明任何Long和blob变量。新值new和旧值old也不能是表中的任何long和blob列。
  l         不同类型的触发器(如DML触发器、INSTEAD OF触发器、系统触发器)的语法格式和作用有较大区别。
  在scott用户下,创建三个触发器:
  Sql代码
  -- 语句级触发器  
  -- 禁止员工在休息日改变雇员信息  
  create or replace trigger tr_sec_emp  
  -- before:在DML事件之前执行  
  before insert or update or delete on emp
  -- 如果在这里没有指定是行级还是语句级触发器,默认是 FOR EACH STATEMENT  
  begin 
  if to_char(sysdate,'DAY','nls_date_language=AMERICAN')  
  in('SAT','SUN') then 
  case 
  -- 当触发事件是Insert操作时,该条件谓词返回值为True,否则为False  
  when inserting then 
  raise_application_error(-20001,'不能在休息日增加雇员信息!');  
  -- 当触发事件是Update操作时,该条件谓词返回值为True,否则为False  
  when updating then 
  raise_application_error(-20002,'不能在休息日修改雇员信息!');  
  -- 当触发事件是Delete操作时,该条件谓词返回值为True,否则为False  
  when deleting then 
  raise_application_error(-20003,'不能在休息日删除雇员信息!');  
  end case;  
  end if;     
  end;  
  /