`
wjheye
  • 浏览: 83793 次
  • 性别: Icon_minigender_1
  • 来自: 河南
社区版块
存档分类
最新评论

Oracle_学习开发子程序_触发器

阅读更多
触发器是指存放在数据库中,并被隐藏执行的存储过程。在Oracle8i之前,只允许基于表或视图的DML操作(insert,update,delete)建立触发器,在oracle8i之后,不仅支持DML操作,也允许基于系统事件(启动数据库,关闭数据库,登录)和DDL操作建立触发器。
一、触发器简介
   触发器是指隐含执行的存储过程,它可以使用PL/SQL,java和C进行开发,当发生特定事件(例如:修改表、建立对象、登录数据库)时,Oracle会自动执行触发器的相应代码。
触发器由触发事件、触发条件和触发操作三部分组成。
1、触发事件
触发事件是指触发器被触发的SQL、数据库事件和用户事件,在oracle8i之前,触发事件只能是DML操作,在oracle8i之后,不仅支持DML事件,而且还增加了其他事件,具体事件如下:

启动和关闭例程
Oracle错误信息
用户登陆和关闭会话
特定表和视图的DML操作
DDL语句

2、触发条件(可选)
触发条件是指使用when子句指定一个boolean表达式,当表达式返回true时,则执行触发器相应代码,如果表达式返回false或unknown,则不会执行触发器相应代码。
3、触发操作
触发操作是指包含SQL语句和其他执行代码的PL/SQL块,不仅可以使用PL/SQL开发,也可以使用java或c语言开发,当触发条件为true时,会自动执行触发操作的相应代码。但是在编写触发器执行代码时,需要注意一下限制:

触发代码大小不能超过32k,如果确实需要使用大量代码建立触发器,应该首先建立存储过程,然后在触发器中使用call语句调用存储过程。
触发器代码只能包括insert、update和delete语句,而不能包括DDL语句(create、drop、alert)和事务控制语句(commit,rollback和savepoint)。

二、建立DML触发器
    当建立DML触发器时,需要指定触发时机(before和after)、触发事件(insert、select、update、delete)、表名、触发类型、触发条件以及触发操作。
1、触发时机
  触发时机是指触发器的触发时间,当指定before关键字时,表示在执行DML操作之前触发触发器;当指定after关键字时,表示在执行DML操作之后触发触发器。
2、触发事件
触发条件是指被引起触发器执行的DML语句,即insert、update、delete操作。即可以使用单个触发事件,也可以组合多个触发事件。
3、表名
因为DML触发器是针对特定表执行的,所以必须指定DML操作所对应的表名。
4、触发类型
触发类型用于指定当触发事件发生后,需要执行几次触发操作,如果指定语句触发类型(默认),则只会执行一次触发器代码,如果指定行触发器,则会在每个被作用行上执行一次触发器。
5、触发条件
触发条件用于指定执行触发器代码的条件,只有当条件为true时,才会执行触发器代码,当编写DML触发器时,只能在行触发器上执行触发条件。
6、触发操作
触发操作用于指定触发器执行的代码,如果使用PL/SQL存储过程、java存储过程或外部存储过程,则在触发操作中使用call语句调用相应过程。如果使用PL/SQL匿名块编写触发操作,则按照以下格式编写。
[declare]
  定义变量、常量等。
begin
  编写SQL语句或PL/SQL块。
exception
  编写例外处理语句。
end;
7、DML触发器触发顺序
(1)、DML触发器在单行数据上执行顺序
    对于单行数据而言,无论是语句触发器、还是行触发器,都执行一次,并且执行顺序是
    before语句触发器、before行触发器、DML操作,after行触发器、after语句触发器。
(2)、DML触发器在多行数据上执行顺序
   对于多行数据而言,语句触发器只执行一次,而行触发器则在每个作用行上都执行一次。
三、语句触发器
语句触发器是当执行DML语句时被隐含执行的触发器。注意语句触发器时,不能记录列数据的变化。建立语句触发器的语法如下:
Oracle代码
create or replace trigger trigger_name    
   timing event1[or event2 or event3]   
on table_name   
pl/sql block;  

create or replace trigger trigger_name 
   timing event1[or event2 or event3] 
on table_name 
pl/sql block; 


如上所示:trigger_name用于指定触发器名称,timing用于指定触发时机(before和after),event1用于指定指定触发事件(insert、update、delete),table_name用于指定DML操作对应的表名。
1、建立before语句触发器
   为了禁止工作人员在休息日改变雇员信息,可以建立before语句触发器,以实现数据的安全保护,示例如下:
Oracle代码
create or replace trigger trigger_before   
before insert or update or delete on cip_tmps   
begin   
     if to_char(sysdate,'DY','nls_date_language=AMERICAN')   
      IN ('STA','SUN','THU','WED') then   
      raise_application_error(-20001,'不能在周末修改数据');   
      end if;   
end;  

create or replace trigger trigger_before 
before insert or update or delete on cip_tmps 
begin 
if to_char(sysdate,'DY','nls_date_language=AMERICAN') 
  IN ('STA','SUN','THU','WED') then 
  raise_application_error(-20001,'不能在周末修改数据'); 
  end if; 
end; 


  2、使用条件谓词
当在触发器中同时包含多个触发时间(insert、update、delete),为了在触发器代码中区分具体的触发事件、可以使用以下三个条件谓词:

INSERTING:当触发条件是insert操作时,该条件谓词返回值为true,否则返回值为false。
UPDATING:当触发条件是update操作时,该条件谓词返回值为true,否则返回值为false。
DELETING:当触发条件是delete操作时,该条件谓词返回值为true,否则返回值为false。

下面示例说明在触发器中使用这三个条件谓词的方法,示例如下:
Oracle代码
create or replace trigger trigger_before   
before insert or update or delete on cip_tmps   
begin   
     if to_char(sysdate,'DY','nls_date_language=AMERICAN')   
      IN ('STA','SUN','THU','WED') then   
      case    
      when inserting then   
        raise_application_error(-20001,'不能在周末添加数据');   
      when updating then   
        raise_application_error(-20002,'不能在周末修改数据');   
      when deleting then   
        raise_application_error(-20003,'不能在周末删除数据');   
        end case;   
      end if;   
end;  

create or replace trigger trigger_before 
before insert or update or delete on cip_tmps 
begin 
if to_char(sysdate,'DY','nls_date_language=AMERICAN') 
  IN ('STA','SUN','THU','WED') then 
  case 
  when inserting then 
    raise_application_error(-20001,'不能在周末添加数据'); 
  when updating then 
    raise_application_error(-20002,'不能在周末修改数据'); 
  when deleting then 
    raise_application_error(-20003,'不能在周末删除数据'); 
end case; 
  end if; 
end;


3、建立after语句触发器
在往cip_temp表中插入数据时,同时往cip_temps表中插入数据,必备条件是,cip_temp表中必须有一个字段标示是最后插入的那条记录。
Oracle代码
create or replace trigger trigger_after   
after insert on cip_temp   
begin   
insert into cip_temps (select * from(select * from cip_temp order by id) where rownum=1);   
end;  

create or replace trigger trigger_after 
after insert on cip_temp 
begin 
insert into cip_temps (select * from(select * from cip_temp order by id) where rownum=1); 
end; 
四、建立行触发器
行触发器是指执行DML操作时,每作用一行就触发一次触发器。建立行触发器语法如下:
Oracle代码
create or replace trigger trigger_name    
   timing event1[or event2 or event3]   
on table_name   
[REFERENCING NEW AS NEW | OLD AS OLD]   
for each row   
pl/sql block;  

create or replace trigger trigger_name 
   timing event1[or event2 or event3] 
on table_name 
[REFERENCING NEW AS NEW | OLD AS OLD] 
for each row 
pl/sql block; 


如上所示:trigger_name用于指定触发器名称,timing用于指定触发时机(before和after),event1用于指定指定触发事件(insert、update、delete),table_name用于指定DML操作对应的表名。REFERENCING 子句用于指定引用新、旧、数据方式,默认情况下使用old修饰符引用旧数据,使用new修饰符是引用新数据。for each row表示建立行触发器。
1、建立before行触发器
确保员工工资不能涨价,示例如下:
Oracle代码
create or replace trigger trigger_before_row   
before update on cip_tmp   
for each row   
begin   
  if(:new.id <>:old.id) then   
  raise_application_error(-20001,'员工工资不能调整');   
  end if;   
end;  

create or replace trigger trigger_before_row 
before update on cip_tmp 
for each row 
begin 
  if(:new.id <>:old.id) then 
  raise_application_error(-20001,'员工工资不能调整'); 
  end if; 
end; 

2、建立after行触发器
做到更新、删除、添加一个表中的数据,则另一个表也相应的更新、删除、添加。
Oracle代码
create or replace trigger trigger_after_row   
after insert or update or delete on cip_test   
for each row   
declare   
v_update int;   
v_delete int;   
begin   
case    
  when inserting then   
    insert into cip_temps values(:new.name,:new.age,:new.address,:new.id);   
  when updating then   
      select count(*) into v_update from cip_temps where id=:old.id;   
      if(v_update=0) then   
      insert into cip_temps values(:new.name,:new.age,:new.address,:new.id);   
      else   
            update cip_temps set name=:new.name,age=:new.age,address=:new.address    
            where id=:old.id;   
      end if;   
  when deleting then   
    select count(*) into v_delete from cip_temps where id=:old.id;   
    if(v_delete<>0)then   
     delete from cip_temps where id=:old.id;   
    end if;   
   end case;      
end;  

create or replace trigger trigger_after_row 
after insert or update or delete on cip_test 
for each row 
declare 
v_update int; 
v_delete int; 
begin 
case 
  when inserting then 
    insert into cip_temps values(:new.name,:new.age,:new.address,:new.id); 
  when updating then 
  select count(*) into v_update from cip_temps where id=:old.id; 
  if(v_update=0) then 
  insert into cip_temps values(:new.name,:new.age,:new.address,:new.id); 
  else 
            update cip_temps set name=:new.name,age=:new.age,address=:new.address 
            where id=:old.id; 
  end if; 
  when deleting then 
    select count(*) into v_delete from cip_temps where id=:old.id; 
    if(v_delete<>0)then 
     delete from cip_temps where id=:old.id; 
    end if; 
   end case;   
end; 


3、限制行触发器
当使用行触发器时,默认情况下会作用在每行执行一次触发器,为了在特定条件下执行行触发器代码,就需要使用when子句对触发条件加以限制。
示例如下:
Oracle代码
create or replace trigger trigger_after_row_when   
after  update or delete on cip_test   
for each row   
when (old.name='aa8')   
declare   
v_update int;   
begin   
case    
  when updating then   
      select count(*) into v_update from cip_temps where id=:old.id;   
    if(v_update=0) then   
     insert into cip_temps values(:new.name,:new.age,:new.address,:new.id);   
    else   
update cip_temps set name=:new.name,age=:new.age,address=:new.address where id=:old.id;   
    end if;   
   end case;      
end;  

create or replace trigger trigger_after_row_when 
after  update or delete on cip_test 
for each row 
when (old.name='aa8') 
declare 
v_update int; 
begin 
case 
  when updating then 
  select count(*) into v_update from cip_temps where id=:old.id; 
if(v_update=0) then 
insert into cip_temps values(:new.name,:new.age,:new.address,:new.id); 
else 
update cip_temps set name=:new.name,age=:new.age,address=:new.address where id=:old.id; 
end if; 
   end case;   
end; 

4、DML触发器使用注意事项
当编写DML触发器时,触发器代码不能从触发器所对应的表中读取数据。
5、实现参照完整性
参照完整性是指两个表具有主从关系(主外健关系),当删除主表数据时,必须确保相应的从表的数据也被删除,可以在定义外键约束时指定on delete cascade。
五、行触发器和语句触发器区别
1、行触发器有 for each row子句。语句触发器没有for each row 子句。
2、行触发器,可以有 when 作为触发限制,可以使用new/old。语句触发器不能有when 作为触发限制。
3、行触发器:对应DML语句所影响到的表中的每一行,触发器都要执行一遍。
4、语句触发:对应DML语句所影响到的表中的所有行,触发器只执行一遍。
对表进行行级触发的,则该表暂时不能操作(即该表已经成为变异表)表 级触发器与此不同

文章信息来源:http://shawnfree.iteye.com/blog/359240
分享到:
评论

相关推荐

    oracle_commond.rar_odbc api_oracle_oracle 客户端_oracle sql_sql

    Oracle SQL是Oracle数据库特有的SQL方言,它扩展了标准SQL,增加了许多高级功能,如物化视图、分区表、存储过程、触发器等。在"oracle常用命令集.sql"中,可能包含了如DML(INSERT、UPDATE、DELETE)语句,DDL...

    Oracle_plsql讲义:第22章 创建子程序和包.ppt

    Oracle PL/SQL 子程序和包的概念和应用 本章要点: * 理解子程序(过程、函数)及包的概念 * 掌握如何创建、执行和删除过程、函数及包的方法 * 了解形参和实参的区别以及不同参数模式的特征 * 灵活使用过程、函数...

    Oracle_database_11g_SQL开发指南

    总的来说,《Oracle_database_11g_SQL开发指南》是一本全面且实用的教程,无论你是刚接触Oracle的新手,还是希望通过学习深化数据库知识的专业人士,都能从中受益。配合提供的PDF文档,你可以随时随地学习和查阅,...

    BBS.rar_oracle_oracle projects_oracle项目

    1. **Oracle SQL**:学习和掌握Oracle特定的SQL语法,如PL/SQL过程语言,用于创建存储过程、函数和触发器等复杂逻辑。 2. **数据库设计**:理解如何根据BBS论坛的需求进行表结构设计,包括主键、外键、索引等,以...

    Oracle_PLSQL.rar_Java plsql_oracle_oracle doc_pl sql_plsql

    在Oracle数据库环境中,PL/SQL被广泛用于开发存储过程、函数、触发器、游标和包,以实现复杂的业务逻辑和数据处理任务。本文将深入探讨Oracle PL/SQL的相关知识点,并结合Java进行集成开发。 1. **PL/SQL基础** - ...

    oracle_plsql学习资料

    9. **子程序和包**:存储过程和函数是可重用的代码单元,用于执行特定任务。包是包含相关过程、函数和变量的集合,提供模块化和封装。 10. **游标变量和记录类型**:游标变量用于存储游标的当前状态,而记录类型...

    数据库oracle触发器课件

    在Oracle数据库中,子程序(过程和函数)可以存储在数据字典中,成为存储子程序,也可以作为局部子程序在PL/SQL语句块内部定义。存储子程序在创建后被编译成伪代码(p-code)存储在数据库中,可以被具有EXECUTE权限...

    shujuku.rar_Oracle javaweb_javaweb oracle_oracle_数据库面试

    Java Web开发则涉及到Web应用程序的设计、构建和部署,其中数据库交互是核心部分。面试中可能涉及的知识点包括: 1. Servlet和JSP:理解Servlet生命周期,如何使用JSP和Servlet进行动态网页开发,以及它们之间的...

    oracle_oracle_oraclepl/sql_

    5. **子程序**:包括过程(PROCEDURE)和函数(FUNCTION),它们可以封装代码并多次调用,提高代码复用性。函数可返回一个值,而过程不返回。 6. **游标**:游标用于处理SQL查询结果集,允许逐行操作数据,常用于...

    oracle触发器调用存储过程

    "Oracle触发器调用存储过程" Oracle触发器可以调用存储过程,以实现业务逻辑的自动化执行。然而,在触发器中调用存储过程时,需要注意事务的隔离性,以避免出现锁定和死锁的问题。Oracle自治事务(Autonomous ...

    OraclePL-SQL.rar_ORACLE PL_oracle_oracle sql

    Oracle PL/SQL是Oracle数据库系统中的重要组成部分,用于开发存储过程、函数、触发器等数据库对象,以及执行复杂的SQL操作。以下是对Oracle PL/SQL及其相关知识点的详细说明: 1. **Oracle数据库基础**:Oracle...

    oracle_sql_plsql课程资料.zip

    1. Oracle SQL基础:Oracle SQL遵循SQL标准,但增加了许多自己的扩展特性,如子查询、连接查询、集合操作、游标、触发器等。在学习Oracle SQL时,你需要理解如何创建表、视图、索引,以及如何插入、更新和删除数据。...

    ORACLE_PlSql-甲骨文学习笔记

    ### ORACLE_PlSql-甲骨文学习笔记 #### 一、创建表 ##### 创建表一 ```sql CREATE TABLE TABLE_NAME ( AAA INTEGER CONSTRAINT PK_TABLE_NAME PRIMARY KEY, BBB VARCHAR2(10) NOT NULL, DOB DATE, CCC VARCHAR...

    PLSQL.rar_oracle_pl sql_plsql_plsql java_sql

    描述中提到“Oracle,PL/SQL操作手册,主要介绍语法等”,意味着这份资料可能详尽地涵盖了PLSQL的基本语法、数据类型、变量声明、控制结构(如IF-THEN-ELSE、CASE语句)、循环(WHILE、FOR循环)、子程序(过程和函数...

    java-oracle中几十个实用的PLSQL.rar_Java plsql_oracle_oracle java_oracle

    在Java和Oracle的交互中,PL/SQL主要用于处理复杂的数据库操作,如事务处理、存储过程和触发器。 在Java程序中,我们通常使用JDBC(Java Database Connectivity)API来访问和操纵Oracle数据库。JDBC为Java开发者...

    Oracle.SQL必备参考_oracle_

    3. **子查询**:Oracle SQL中的子查询允许在查询中嵌套查询,用于比较、筛选或者组合复杂的数据。 4. **联接操作**:Oracle支持多种类型的联接,包括内连接(INNER JOIN)、外连接(LEFT JOIN, RIGHT JOIN, FULL JOIN)...

    oracle_ppt.zip

    Oracle数据库是全球最广泛使用的商业关系型数据库管理系统之一,由美国甲骨文公司(Oracle Corporation)开发和维护。本课件“oracle_ppt.zip”包含了关于Oracle数据库的详细讲解,旨在帮助学习者深入理解其核心概念...

    《剑破冰山__Oracle开发艺术_》高清PDF+源代码

    《剑破冰山__Oracle开发艺术_》是一本专注于Oracle数据库开发的专业书籍,旨在帮助读者深入理解Oracle数据库的原理,并掌握高效开发技巧。通过阅读这本书的高清PDF版,读者可以全面学习Oracle的各种特性,包括SQL...

    Oracle2BPL-SQL.rar_oracle_pl/sql

    Oracle PL/SQL是一种强大的编程语言,它...学习PL/SQL对于开发Oracle数据库应用程序、维护数据库逻辑和优化性能至关重要。通过阅读Oracle2BPL-SQL.pdf,初学者可以逐步掌握这一强大工具,提升数据库管理和开发的能力。

Global site tag (gtag.js) - Google Analytics