`
keepwork
  • 浏览: 334273 次
  • 性别: Icon_minigender_1
  • 来自: 深圳
社区版块
存档分类
最新评论

Oracle--trigger

 
阅读更多

开发者博客www.developsearch.com

 

 

触发器在数据库里以独立的对象存储,它与存储过程和函数不同的是,存储过程与函数需要用户显示调用才执行,而触发器是由一个事件来启动运行。即触发器是当某个事件发生时自动地隐式运行。并且,触发器不能接收参数。ORACLE事件指的是对数据库的表进行的INSERT、UPDATE及DELETE操作或对视图进行类似的操作。ORACLE将触发器的功能扩展到了触 发ORACLE,如数据库的启动与关闭等。所以触发器常用来完成由数据库的完整性约束难以完成的复杂业务规则的约束,或用来监视对数据库的各种操作,实现 审计的功能。

 

参考文章 :http://blog.csdn.net/indexman/article/details/8023740

 

编写触发器时,需要注意以下几点:
1、触发器不接受参数。
2、一个表上最多可有12个触发器,但同一时间、同一事件、同一类型的触发器只能有一个。并各触发器之间不能有矛盾。
3、在一个表上的触发器越多,对在该表上的DML操作的性能影响就越大。
4、触发器最大为32KB。若确实需要,可以先建立过程,然后在触发器中用CALL语句进行调用。
5、在触发器的执行部分只能用DML语句(SELECT、INSERT、UPDATE、DELETE),不能使用DDL语句(CREATE、ALTER、DROP)。
6、触发器中不能包含事务控制语句(COMMIT,ROLLBACK,SAVEPOINT)。因为触发器是触发语句的一部分,触发语句被提交、回退时,触发器也被提交、回退了。
7、在触发器主体中调用的任何过程、函数,都不能使用事务控制语句。
8、在触发器主体中不能申明任何Long和blob变量。新值new和旧值old也不能是表中的任何long和blob列。
9、不同类型的触发器(如DML触发器、INSTEAD OF触发器、系统触发器)的语法格式和作用有较大区别。

 

创建触发器的一般语法是:

CREATE [OR REPLACE] TRIGGER trigger_name
{BEFORE | AFTER }
{INSERT | DELETE | UPDATE [OF column [, column …]]}
[OR {INSERT | DELETE | UPDATE [OF column [, column …]]}...]
ON [schema.]table_name | [schema.]view_name
[REFERENCING {OLD [AS] old | NEW [AS] new| PARENT as parent}]
[FOR EACH ROW ]
[WHEN condition]
PL/SQL_BLOCK | CALL procedure_name;

 

查看某个表的触发器

select   *   from   all_triggers
where   table_name   = upper( 'tbname ')

 

删除触发器:
DROP TRIGGER trigger_name;

 

禁用或启用触发器
ALTER TIGGER trigger_name [DISABLE | ENABLE ];

 

:old  与 :new 的区别:
顾名思义,new是新插入的数据,old是原来的数据
insert只会有new,代表着要插入的新记录
delete只会有old,代表着要删除的记录
update由于执行的是先删除旧的记录,再插入新的记录,因此new和old都会有,且含义与上面的相同

这两个变量只有在使用了关键字 "FOR EACH ROW"时才存在

 

例1: 建立一个触发器, 当职工表 emp 表被删除一条记录时,把被删除记录写到职工表删除日志表中去。

CREATE TABLE emp_his AS SELECT * FROM EMP WHERE 1=2; 
CREATE OR REPLACE TRIGGER tr_del_emp 
   BEFORE DELETE --指定触发时机为删除操作前触发
   ON scott.emp 
   FOR EACH ROW   --说明创建的是行级触发器 
BEGIN
   --将修改前数据插入到日志记录表 del_emp ,以供监督使用。
   INSERT INTO emp_his(deptno , empno, ename , job ,mgr , sal , comm , hiredate )
       VALUES( :old.deptno, :old.empno, :old.ename , :old.job,:old.mgr, :old.sal, :old.comm, :old.hiredate );
END;
DELETE emp WHERE empno=7788;
DROP TABLE emp_his;
DROP TRIGGER del_emp;
 

 

例2:限制对Departments表修改(包括INSERT,DELETE,UPDATE)的时间范围,即不允许在非工作时间修改departments表。
CREATE OR REPLACE TRIGGER tr_dept_time
BEFORE INSERT OR DELETE OR UPDATE 
ON departments
BEGIN
 IF (TO_CHAR(sysdate,'DAY') IN ('星期六', '星期日')) OR (TO_CHAR(sysdate, 'HH24:MI') NOT BETWEEN '08:30' AND '18:00') THEN
     RAISE_APPLICATION_ERROR(-20001, '不是上班时间,不能修改departments表');
 END IF;
END;
 
例3:限定只对部门号为80的记录进行行触发器操作。
CREATE OR REPLACE TRIGGER tr_emp_sal_comm
BEFORE UPDATE OF salary, commission_pct
       OR DELETE
ON HR.employees
FOR EACH ROW
WHEN (old.department_id = 80)
BEGIN
 CASE
     WHEN UPDATING ('salary') THEN
        IF :NEW.salary < :old.salary THEN

           RAISE_APPLICATION_ERROR(-20001, '部门80的人员的工资不能降');
        END IF;
     WHEN UPDATING ('commission_pct') THEN

        IF :NEW.commission_pct < :old.commission_pct THEN
           RAISE_APPLICATION_ERROR(-20002, '部门80的人员的奖金不能降');
        END IF;
     WHEN DELETING THEN
          RAISE_APPLICATION_ERROR(-20003, '不能删除部门80的人员记录');
     END CASE;
END; 
 
例4:利用行触发器实现级联更新。在修改了主表regions中的region_id之后(AFTER),级联的、自动的更新子表countries表中原来在该地区的国家的region_id。
CREATE OR REPLACE TRIGGER tr_reg_cou
AFTER update OF region_id
ON regions
FOR EACH ROW
BEGIN
 DBMS_OUTPUT.PUT_LINE('旧的region_id值是'||:old.region_id
                  ||'、新的region_id值是'||:new.region_id);
 UPDATE countries SET region_id = :new.region_id
 WHERE region_id = :old.region_id;
END;
 
例5:在触发器中调用过程。
CREATE OR REPLACE PROCEDURE add_job_history
 ( p_emp_id          job_history.employee_id%type
   , p_start_date      job_history.start_date%type
  , p_end_date        job_history.end_date%type
   , p_job_id          job_history.job_id%type
   , p_department_id   job_history.department_id%type
   )
IS
BEGIN
 INSERT INTO job_history (employee_id, start_date, end_date,
                           job_id, department_id)
  VALUES(p_emp_id, p_start_date, p_end_date, p_job_id, p_department_id);
END add_job_history;

--创建触发器调用存储过程...
CREATE OR REPLACE TRIGGER update_job_history
 AFTER UPDATE OF job_id, department_id ON employees
 FOR EACH ROW
BEGIN
 add_job_history(:old.employee_id, :old.hire_date, sysdate,
                  :old.job_id, :old.department_id);
END;
 
创建替代(INSTEAD OF)触发器INSTEAD_OF 用于对视图的DML触发,由于视图有可能是由多个表进行联结(join)而成,因而并非是所有的联结都是可更新的。但可以按照所需的方式执行更新。
创建INSTEAD OF触发器需要注意以下几点:
1、只能被创建在视图上,并且该视图没有指定WITH CHECK OPTION选项。
2、不能指定BEFORE 或 AFTER选项。
3、FOR EACH ROW子可是可选的,即INSTEAD OF触发器只能在行级上触发、或只能是行级触发器,没有必要指定。
4、没有必要在针对一个表的视图上创建INSTEAD OF触发器,只要创建DML触发器就可以了。
例1:
CREATE OR REPLACE VIEW emp_view AS
SELECT deptno, count(*) total_employeer, sum(sal) total_salary
FROM emp GROUP BY deptno;

在此视图中直接删除是非法:
SQL>DELETE FROM emp_view WHERE deptno=10;
DELETE FROM emp_view WHERE deptno=10

ERROR 位于第 1 行:
ORA-01732: 此视图的数据操纵操作非法

但是我们可以创建INSTEAD_OF触发器来为 DELETE 操作执行所需的处理,即删除EMP表中所有基准行:
CREATE OR REPLACE TRIGGER emp_view_delete
   INSTEAD OF DELETE ON emp_view FOR EACH ROW
BEGIN
   DELETE FROM emp WHERE deptno= :old.deptno;
END emp_view_delete;
DELETE FROM emp_view WHERE deptno=10;
DROP TRIGGER emp_view_delete;
DROP VIEW emp_view; 
 
例2:创建复杂视图,针对INSERT操作创建INSTEAD OF触发器,向复杂视图插入数据。
创建视图:
CREATE OR REPLACE FORCE VIEW "HR"."V_REG_COU" ("R_ID", "R_NAME", "C_ID", "C_NAME")
AS
 SELECT r.region_id,
    r.region_name,
    c.country_id,
    c.country_name
 FROM regions r,
    countries c
 WHERE r.region_id = c.region_id;

创建触发器:
CREATE OR REPLACE TRIGGER "HR"."TR_I_O_REG_COU" INSTEAD OF
 INSERT ON v_reg_cou FOR EACH ROW DECLARE v_count NUMBER;
BEGIN
 SELECT COUNT(*) INTO v_count FROM regions WHERE region_id = :new.r_id;
 IF v_count = 0 THEN
    INSERT INTO regions
      (region_id, region_name
      ) VALUES
      (:new.r_id, :new.r_name
      );
 END IF;

 SELECT COUNT(*) INTO v_count FROM countries WHERE country_id = :new.c_id;
 IF v_count = 0 THEN
    INSERT
    INTO countries
      (
        country_id,
        country_name,
        region_id
      )
      VALUES
      (
        :new.c_id,
        :new.c_name,
        :new.r_id
      );
 END IF;
END;
 开发者博客www.developsearch.com
 
分享到:
评论

相关推荐

    Oracle-Pl-Sql.rar

    6. **触发器(TRIGGER)**:触发器是在特定数据库事件(如INSERT、UPDATE或DELETE)发生时自动执行的PL/SQL代码。它们可以用来强制业务规则或执行自动更新。 7. **索引和性能优化**:了解如何使用索引来加速SQL查询...

    Oracle Table Form Trigger

    Oracle Table Form Trigger是Oracle数据库应用开发中的重要概念,主要涉及三方面:Oracle表格(Table)、表单(Form)以及触发器(Trigger)。本篇将详细阐述这三个关键元素及其相互关系。 1. Oracle表格(Table)...

    SQL Optimizer for Oracle - Basic.ppt

    在识别阶段,主要目标是找出可能引起性能瓶颈的SQL语句,这包括开发过程中的原始代码、现存的Procedure、Trigger、View等数据库对象,以及已上线的应用程序。识别的关键在于锁定所有潜在的问题SQL,以便进行后续的...

    underground-php-oracle-manual.pdf

    trigger_error(htmlentities($e['message'], ENT_QUOTES), E_USER_ERROR); } $stid = oci_parse($conn, 'SELECT * FROM table_name'); oci_execute($stid); while (($row = oci_fetch_array($stid, OCI_ASSOC+...

    Oracle-PLSQL-编程语法详解-触发器.docx

    Oracle PL/SQL 中的触发器是数据库管理系统中一种强大的工具,用于响应特定的数据库事件并自动执行预定义的代码块。触发器与存储过程相似,都是包含PL/SQL代码的逻辑单元,但触发器的执行是隐式的,由特定的数据库...

    oracle-sql.rar_oracle

    1. 触发器(TRIGGER):在特定事件(如INSERT, UPDATE, DELETE)发生时自动执行的存储过程。 2. 索引(INDEX):加速查询速度,Oracle支持B树索引、位图索引等多种类型。 3. 视图(VIEW):虚拟表,基于一个或多个...

    oracle-mianshiti.rar_java 面试题_oracle_如何面试oracle

    - **触发器**(Trigger):在特定事件(如INSERT、UPDATE或DELETE)发生时自动执行的代码。 4. **性能优化**: - **EXPLAIN PLAN**:通过分析查询计划来诊断性能问题。 - **绑定变量**:减少硬解析,提高SQL语句...

    Oracle--存储过程与触发器基本操作.docx

    Oracle数据库中的存储过程和触发器是数据库管理中的重要组成部分,它们极大地增强了数据库的灵活性和安全性。存储过程是一组预先编译好的SQL语句,可以封装成一个命名的单元,供后续调用,常用于执行复杂的业务逻辑...

    oracle-ocp-053 复习资料

    这部分也可能会包含触发器(TRIGGER)和存储过程的高级应用,以及数据类型和转换的细节。 "053(101~150).docx"可能会涉及到Oracle数据库的管理,如表空间和数据文件的管理,数据库实例的启动与关闭,以及用户管理和...

    Oracle Trigger

    ### Oracle触发器概念与应用详解 #### 一、引言 在现代数据库管理系统(DBMS)中,触发器是一种重要的机制,用于确保数据的完整性、安全性和一致性。Oracle数据库中的触发器功能尤其强大,允许开发人员根据不同的...

    oracle - 数据同步 实例

    CREATE OR REPLACE TRIGGER TRI_GRADING AFTER INSERT OR DELETE OR UPDATE ON GRADING FOR EACH ROW BEGIN IF INSERTING THEN INSERT INTO SYN_GRADING (ID, DEVICEID, GRADE, INTHEYEAR, GRADINGMAN, CARID,...

    oracle - PLSQL.7z

    8. **触发器(TRIGGER)**: 触发器是数据库对象,当特定的数据库事件(如INSERT、UPDATE或DELETE)发生时自动执行。它们可以用来实施复杂的业务规则和审计功能。 9. **动态SQL**: 动态SQL允许在运行时构建和...

    oracle-impdp&expdp总结

    ### Oracle impdp & expdp 总结 #### 一、Oracle expdp 操作总结 **1. 创建目录对象** 为了能够使用 Oracle 数据泵 (Data Pump) 工具进行数据导入导出操作,首先需要创建一个目录对象来指定备份文件存放的位置。 ...

    Oracle-把触发器看透.docx

    CREATE [OR REPLACE] TRIGGER trigger_name {BEFORE | AFTER} {INSERT | DELETE | UPDATE [OF column [, column …]]} [OR {INSERT | DELETE | UPDATE [OF column [, column …]]}...] ON [schema.]table_name | ...

    ORACLE-PLSQL及存储过程自学资料

    最后,触发器(TRIGGER)是数据库级别的事件驱动程序,它们可以在特定的数据库操作(如INSERT, UPDATE, DELETE)发生时自动执行,用于实现数据验证、日志记录等功能。 通过本自学资料的学习,你将掌握Oracle PL/SQL...

    Oracle-存储过程、函数、触发器和包.ppt

    CREATE TRIGGER trigger_name BEFORE|AFTER|INSTEAD OF {INSERT|UPDATE|DELETE} ON table_name FOR EACH ROW [WHEN condition] BEGIN /* 触发操作 */ END; ``` **包**是将相关的存储过程、函数和其他数据库对象...

    oracle_11gR212

    在“oracle_11gR2_12 触发器TRIGGER - 介绍,创建,使用,级联(删除,插入和更新).avi”和“.txt”文件中,可能包含了触发器的详细讲解,包括实际示例、步骤指导和可能遇到的问题。这些资源可以帮助你更深入地了解如何在...

    oracle trigger at a certain time

    在Oracle数据库中,触发器(Trigger)是一种存储过程,它会在特定的数据库操作(如INSERT、UPDATE或DELETE)发生时自动执行。标题“oracle trigger at a certain time”指的是创建一个定时触发器,即在特定时间点...

    Oracle_11G_最新数据库备份和恢复操作手册

    grant alter session,create cluster,create database link,create sequence,create session,create synonym,create table,create view,create procedure,create trigger,query rewrite to ARAdmin; ``` 这些权限...

    oracleform常用Trigger的触发时机.pdf

    oracleform常用Trigger的触发时机.pdf

Global site tag (gtag.js) - Google Analytics