Oracle数据库之PLSQL触发器
程序员文章站
2022-05-07 14:16:32
...
--=======触发器============ --是一段命名的PL/SQL代码块,只不过该代码块在特定的条件下被触发并且执行。 --对于这样的代码我们称之为触发器 --======触发器的分类============= --通常根据触发条件以及触发级别的不同分为DML触发器,INSTEAD OF 触发器,系统事件触发器。 ---DML触发器: ORACLE 对DML语句进行触发, --可以在DML操作前或操作后进行触发,并且可以对每个行或语句操作上进行触发。 ---INSTEAD OF 触发器 :在ORACLE里,对于简单视图,可以直接使用DML进行操作, --而复杂视图则不能直接使用DML,因此INSTEAD OF 触发器应运而生。 --INSTEAD OF 触发器主要是为解决复杂视图不能执行DML而创建。 ---系统事件触发器 --在 ORACLE 数据库系统的事件中进行触发,如ORACLE系统的启动与关闭等. --使用系统触发器,便于系统跟踪,监测数据库变化情况等。 --============触发器的用途========= --控制DDL语句的行为,如通过更改、创建或重命名对象 --控制DML语句的行为,如插入、更新和删除 --实施参照完整性、复杂业务规则和安全性策略 --在修改视图中的数据时控制和重定向DML语句 --通过创建透明日志来审核系统访问和行为的信息 --=======DML语句触发器================== --组成部分 描述 可能值 --触发时间 触发事件的时间顺序 before,after --触发事件 DML语句是触发事件 insert,update,delete --触发器类型 触发器被执行的次数 statement,row --触发器体 该触发器将要执行的动作 完整的PLSQL块 --======DML触发器的类型=========== --语句级触发器 --行级触发器 (for each row) --区别:触发的次数不同,如果DML语句影响1行,那么两种效果一样 -- 如果影响多行,行级触发次数比语句级触发次数多. --=========DML触发器的触发顺序=============== --在单行数据上的触发顺序(触发代码仅被执行一次) ---BEFORE 语句级触发器 ------BEFORE 行级触发器 ------AFTER 行级触发器 -- AFTER 语句级触发器 --.在多行数据上的触发顺序(语句级触发器仅被执行一次,行级触发器在每个作业行上被执行一次) --BEFORE 语句级触发器 ------BEFORE 行级触发器 ------AFTER 行级触发器 ----------BEFORE 行级触发器 ----------AFTER 行级触发器 --AFTER 语句级触发器 --==创建触发器的语法 CREATE [OR REPLACE] TRIGGER trigger_name {BEFORE | AFTER | INSTEAD OF} --定义触发类型,即那一种或多种DML以及特定的列 {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] --满足条件才会触发 BEGIN trigger_body; END; --=====在行级触发器中使用被插入、更新或删除的记录中的列值,(只能用在行级触发) ---可以使用NEW和OLD限定符来表示 --- :old 修饰符访问操作完成前列的值 --- :new 修饰符访问操作完成后列的值 ---============================================ --触发事件 :old.id :new.id --insert :old.id结果 为null 数据库会把 的值的值插入id列 --update 在update之前的值 update之后的新值 --delete delete之前的原始值 字段null --需求:完成sequence的调用( 自动生成主键) --准备表: create table t1 (id number(4) ,c1 number(4)); create sequence s;--创建系列s create or replace trigger get_pk --在insert , t1表之前触发 before insert on t1 for each row --每一行都被触发 declare begin -- :new是个记录类型的变量,结构类似于表结构,每条新插入的记录存储在其中。 --定义行级的before insert触发器,在插入记录之前,改变:new里的值,从而实现自动产生主键值。 select s.nextval into :new.id from dual; dbms_output.put_line(':new.id'|| :new.id);-- 1,2,3,4, dbms_output.put_line(' :old.id'|| :old.id); -- 没有 end; --执行 会触发 get_pk触发器. insert into t1 values (100,100); insert into t1 values (100,200); insert into t1 values (100,300); --再次查询:select * from t1 ; -- id c1 -- 1 100 -- 2 200 -- 3 300 --==== update :new , :old测试 create or replace trigger up_pk before update on t1 for each row declare begin dbms_output.put_line('update :new .c1'|| :new.c1);--400 dbms_output.put_line('update :old.c1'|| :old.c1); -- 300 end; -- update:触发up_pk触发器 update t1 set c1 = 400 where id = 3; -- :new.c1 400 , :old.c1 300 --==== 测试delete create or replace trigger de_pk before delete on t1 for each row declare begin dbms_output.put_line('delete :new .c1'|| :new.c1);--没有 dbms_output.put_line('delete :old.c1'|| :old.c1);--400 end; -- delete:触发de_pk触发器 delete from t1 where id = 3; -- :new.c1 没有 , :old.c1 400 --=========跟记录更新t1表的时间. -- c2存放修改前的值, c3存储修改后的值 create table t_log (c1 varchar2(30),c2 number(4),c3 number(4) , c4 date); --在t1表上创建触发器 -- for each row : update一行就触发1次.update 2行就触发2次 create or replace trigger update_log before update on t1 for each row -- before update on t1 这里有错, :old.c1, :new.c1不能用在表级触发器 declare begin insert into t_log values (' Before update on t1 ',:old.c1, :new.c1 , sysdate); end; -- 测试 ,行级 ,表级触发的区别 create table t_log (c1 varchar2(30),c4 date); --在t1表上创建触发器 -- update 1行触发1次,update 2行 也是触发1次 create or replace trigger update_log -- before update on t1 for each row before update on t1 declare begin insert into t_log values (' Before update on t1', sysdate); end; --== when限制条件的行级触发器 create or replace trigger update_log before update on t1 for each row when ( old.id = 1) -- 当满足这个条件的时候触发 declare begin insert into t_log values (' Before update on t1', sysdate); end; -- == of的使用 create or replace trigger update_log before update on t1 of id for each row --表示当id 被update时 才会被触发 when ( old.id = 1) -- 当满足这个条件的时候触发 declare begin insert into t_log values (' Before update on t1', sysdate); end; -- ==对于复杂的数据完整性,参照完整性,可以通过DML触发器来完成普通约束所不能完成的任务 -- 级联更新 CREATE OR REPLACE TRIGGER update_cascade AFTER DELETE OR UPDATE OF deptno ON dept FOR EACH ROW BEGIN -- updaing :修改了返回true ,否则 false -- :old.deptno<>:new.deptno :修改前的值 不等于 修改后的值 IF (UPDATING AND :old.deptno<>:new.deptno) THEN UPDATE emp SET deptno=:new.deptno WHERE deptno=:old.deptno; END IF; -- deleting :删除true ,否false; IF DELETING THEN DELETE FROM emp WHERE deptno=:old.deptno; END IF; END; --查看触发器 名字,状态 select trigger_name,status from user_triggers where table_name='UPDATE_CASCADE'; --查看触发器源码 select line,text from user_source where name='TR_DEL_UPD_DEPTNO'; --禁用触发器 --当触发器被禁用后,则表上的DML操作将不会触发该触发器, --直到该触发器被解除禁用(alter trigger trigger_name disable) alter trigger tr_emp_sal disable; --启用触发器 -- 被禁用的触发器可以被解除禁用(alter trigger trigger_name enable) alter trigger tr_emp_sal enable; -- 禁用、启用表上的所有触发器 alter table emp disable all triggers; alter table emp enable all triggers; --重新编译触发器 alter trigger tr_emp_sal compile; -- 删除触发器 drop trigger tr_emp_sal;