ITPub博客

首页 > Linux操作系统 > Linux操作系统 > ORACLE TRIGGER

ORACLE TRIGGER

原创 Linux操作系统 作者:1004050304 时间:2013-09-10 00:53:31 0 删除 编辑
今天在做项目维护中,发现项目中有很多的触发器,以前也没有对trigger有过了解,今天花了点时间学习了一下TRIGGER:

触发器有三种类型:
1、DML触发器
2、INSTEAD OF触发器
3、系统触发器

A、触发器类似存储过程和函数,都有声明,执行和异常处理过程的PL/SQL块.简单的来说
B、触发器就是在对数据库执行某些操作时(如:INSERT,UPDATE,DELETE),而被动发生的一些事件.
C、触发器在数据库里以独立的对象存储,所以可以重名,它与存储过程和函数不同的是,触发器是由一个事件来启动的,不需要显示调用才执行.
(注意:触发器不能接收参数,一个表上最多12个触发器,
同一时间,同一事件,同一类型的触发器只能有一个,触发器越多,对表的DML操作的性能影响就越大.
触发器最大为32KB,可以通过触发器中调用过程解决.
触发器的执行部分只能用DML语句(select,insert,update,delete),不能使用DDL语句(create,alter,drop).
触发器中不能包含事务控制语句(commit,rollback,savepoint),因为触发器是触发语句的一部分,和触发语句一起提交回退.
触发器主体中调用的任何过程,函数都不能使用事务控制语句.
触发器主体中不能申明任何long和blob变量,新值和旧值也不能是表中的任何long和blob列.
)

触发器语法:
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;

INSERTING:当触发事件是INSERT时,取值为TRUE,否则为FALSE
UPDATING:当触发事件是UPDATE时,取值为TRUE,否则为FALSE
DELETING:当触发事件是DELETE时,取值为TRUE,否则为FALSE

FOR EACH ROW:表示每一条记录都会产生触发,而默认的语句及只会产生一次触发.

下面是我自己做的几个关于触发器的例子:

CREATE TABLE T_TRIGGER AS SELECT OBJECT_ID,OBJECT_TYPE,STATUS FROM ALL_OBJECTS;
CREATE TABLE T_TRIGGER_LOG AS SELECT OBJECT_ID,OBJECT_TYPE,STATUS FROM ALL_OBJECTS WHERE 1=2;
1、建立一个触发器,当表被删除一条记录时,把被删除记录写到日志表中去
CREATE OR REPLACE TRIGGER TRI_T_TRIGGER_DEL
BEFORE DELETE
ON T_TRIGGER
FOR EACH ROW
  BEGIN
    INSERT INTO T_TRIGGER_LOG(OBJECT_ID,OBJECT_TYPE,STATUS)
    VALUES(:OLD.OBJECT_ID,:OLD.OBJECT_TYPE,:OLD.STATUS);
  END;

SELECT * FROM T_TRIGGER;
DELETE T_TRIGGER WHERE OBJECT_ID=20;
SELECT * FROM T_TRIGGER_LOG;


--DROP TRIGGER TRI_T_TRIGGER_DEL;
2、限制对T_TRIGGER表修改,即不允许在非工作时间修改T_TRIGGER表
CREATE OR REPLACE TRIGGER TRI_T_TRIGGER_DEL
BEFORE INSERT OR DELETE OR UPDATE
ON T_TRIGGER
BEGIN
  IF(TO_CHAR(SYSDATE,'DAY') IN ('星期六','星期日')) OR (TO_CHAR(SYSDATE,'HH24:MI') NOT BETWEEN '8:30' AND '16:00') THEN
    RAISE_APPLICATION_ERROR(-20001,'不是上班时间,不能修改');
  END IF;
END;
INSERT INTO T_TRIGGER VALUES(0,'TRIGGER','VALID');
DELETE T_TRIGGER WHERE OBJECT_ID=3;
UPDATE T_TRIGGER SET OBJECT_ID=20 WHERE OBJECT_ID=3;


3、有限定条件的触发器
CREATE OR REPLACE TRIGGER TRI_T_TRIGGER_DEL
BEFORE UPDATE OF OBJECT_ID OR DELETE
ON T_TRIGGER
FOR EACH ROW
WHEN (OLD.OBJECT_ID =3)
BEGIN
  CASE
    WHEN UPDATING('OBJECT_ID') THEN
      IF :NEW.OBJECT_ID < :OLD.OBJECT_ID THEN
        RAISE_APPLICATION_ERROR(-20001,'不能更改为更小值');
      END IF;
    WHEN DELETING THEN
      RAISE_APPLICATION_ERROR(-20001,'不能删除OBJECT_ID为3的数据');
    END CASE;
END;
UPDATE T_TRIGGER SET OBJECT_ID=2 WHERE OBJECT_ID=3;
DELETE T_TRIGGER WHERE OBJECT_ID=3;


4、利用触发器实现级联更新
CREATE TABLE T_USER(ID NUMBER,NAME VARCHAR2(10),ADDR NUMBER);
INSERT INTO T_USER VALUES(1,'1111',1);
INSERT INTO T_USER VALUES(2,'2222',2);
CREATE TABLE T_ADDR(ID NUMBER,ADDR_DESC VARCHAR2(20));
INSERT INTO T_ADDR VALUES(1,'JKLJKJKJ');
INSERT INTO T_ADDR VALUES(2,'JKLJKLJLK');
DROP TRIGGER TRI_T_TRIGGER_DEL;
CREATE OR REPLACE TRIGGER TRI_T_TRIGGER_DEL
AFTER UPDATE OF ID
ON T_ADDR
FOR EACH ROW
BEGIN
  UPDATE T_USER SET ID = :NEW.ID WHERE ID = :OLD.ID;
END;
UPDATE T_ADDR SET ID = 3 WHERE ID = 2;
SELECT * FROM T_USER;


5、在触发器中调用过程(注意:触发器在执行过程中会将表锁住,所以调用的存储过程不能和触发器操作同一张表)
CREATE OR REPLACE PROCEDURE PRO_TRIGGER
IS
BEGIN
  INSERT INTO T_ADDR VALUES(10,'1010010');
END PRO_TRIGGER;
DROP TRIGGER TRI_T_TRIGGER_DEL;
CREATE OR REPLACE TRIGGER TRI_T_TRIGGER_DEL
AFTER UPDATE OF NAME ON T_USER
FOR EACH ROW
BEGIN
  PRO_TRIGGER;
END;
UPDATE T_USER SET NAME='FFFF' WHERE ID=1;
SELECT * FROM T_ADDR;



INSTEAD OF触发器
只能被创建在视图上,并且该视图没有指定WITH CHECK OPTION选项
不能指定BEFORE或AFTER选项
FOR EACH ROW是可选的

系统触发器
ORACLE 10G提供的系统事件触发器可以在DDL或数据库系统上被触发.









来自 “ ITPUB博客 ” ,链接:http://blog.itpub.net/25285600/viewspace-772443/,如需转载,请注明出处,否则将追究法律责任。

上一篇: ORACLE我来了
下一篇: ArrayList源码分析
请登录后发表评论 登录
全部评论

注册时间:2013-09-04

  • 博文量
    6
  • 访问量
    6894