2020-06-25

触发器 trigger

触发器是被指定关联到一个表的数据对象,它不需要调用,当对一个表的特别事件出现时,它就被激活。触发器的代码也是由SQL语句组成的,因此用在存储过程中的语句也可以用再触发器的定义中。触发器是一类特殊的存储过程,与表的关系密切,用于保护表中的数据,当有操作影响到触发器保护的数据时,触发器将自动执行。

(1)DML触发器:当数据库中发生数据操作语句(DML)事件时调用DML触发器。DML事件包括用表或视图的 insert语句,update语句和delect语句,因此DML触发器可分为3种。

(2)代替触发器:由于oracle中不能直接对两个以上的表建立的视图进行操作,所以给出了代替触发器。它是oracle专门为进行视图操作的一种处理方式。

3)系统触发器:系统触发器也由相应的事件触发,但它的激活一般基于对数据库系统所进行得操作,如数据定义语句(DDL),启动或关闭触发器,连接或断开,服务器错误等系统事件。

命令创建触发器:

--语法格式create or replace trigger 触发器的名称before /after/instead ofinsert/update/delete on for each row

说明:

触发器名称:触发器的名字与过程名和包的名字不一样,它有单独的名字空间,因此触发器名可以和表名或过程名同名,但在同一个方案中的触发器名不能相同。

after:触发器在指定操纵都成功执行后触发,如after insert 表示在向表中插入数据后激活触发器

before:触发器在指定操作执行前触发,如before insert 表示在向表中插入数据前激活触发器

instead of: 指定创建代替触发器,触发器指定的事件不执行,而执行触发器本身的操作。

delete,insert,update:指定一个或多个触发器,多个触发器事件之间用 or 连接

of:指定在某列上update触发器,如果为多列,则需要使用逗号分隔。

for each row:在触发器定义中,如果未使用for each row 子句则表示触发器为语句触发器,触发器在激活后只执行一次,而不管这一操作将影响多行。

 

创建触发器有以下限制:

(1) 代码大小。触发器代码大小必须小于32K。

(2) 触发器中有效语句可以包括DML语句,但不能包括DDL语句。ROLLBACK、COMMIT、SAVEPOINT也不能使用。但是,对于系统触发器(system trigger)可以使用CREATE、ALTER、DROP TABLE和ALTER…COMPILE语句。

(3) LONG、LONG RAW和LOB的限制:

     ① 不能插入数据到LONG或LONG RAW;

     ② 来自LONG或LONG RAW的数据可以转换成字符型(如char、varchar2),但是不能超过32K;

     ③ 使用LONG或LONG RAW不能声明变量;

     ④ 在LONG或LONG RAW列中不能使用:NEW和:PARENT;

     ⑤ 在LOB中的:NEW变量不能修改。

(4) 引用包变量的限制。如果UPDATE或DELETE语句检测到当前的UPDATE冲突,则Oracle执行ROLLBACK到SAVEPOINT上并重新启动更新,这样可能需要多次才能成功。

 

创建DML触发器:

--假设数据库中增加一新表school_students_old,表结构和表school_students相同,用来存放从school_students表--中删除的记录。创建一个触发器,当school_students表被删除一行,把删除的记录写到日志表school_students_old中。
create table school_students_old2 //创建新表( STU_ID NVARCHAR2(20) NOT NULL,STU_NAME NVARCHAR2(20) NOT NULL ,STU_SEX NVARCHAR2(20) ,STU_CREDITS NUMBER(2) ,STU_BIRTHDAY DATE , STU_CLASS NVARCHAR2(20) );select * from school_students_old2;create or replace trigger delete_stu //创建触发器 before delete on school_students for each rowbegin insert into school_students_old2 (STU_ID,STU_NAME,STU_SEX,STU_CREDITS,STU_BIRTHDAY,STU_CLASS) values (:old.STU_ID,:old.STU_NAME,:old.STU_SEX,:old.STU_CREDITS,:old.STU_BIRTHDAY,:old.STU_CLASS);end delete_stu;select * from school_students;select * from school_students_old;

 

创建代替触发器:

--在数据库中创建视图和触发器,以说明替代触发器。create or replace view stu_avgasselectRESULT_STU,avg(result_number) as stu_avg fromSCHOOL_RESULTgroup by RESULT_STU;select * from stu_avg where RESULT_STU='201632218031';delete from stu_avg where RESULT_STU='201632218031';create or replace trigger tr_stu_avg_deleteinstead of delete on stu_avg for each rowbegin delete from SCHOOL_RESULT where result_stu=:old.result_stu;end tr_stu_avg_delete;

 

创建系统触发器:

--创建当一个用户userA登录时自动记录一些信息的触发器。create table login_log( v_user varchar2(100), v_date date);create or replace trigger tr_login_log after logon on schema declare v_name VARCHAR2(20); begin select user into v_name from dual; insert into login_log values(v_name,sysdate); end tr_login_log; select * from login_log; 

 

启用和禁用触发器:

在oracle中,与过程,函数,包不同,触发器是可以被禁用和启用的,在有大量数据要导入数据库中时,为了避免触发相应的触发器以节省处理时间,可以禁用触发器,使其暂时失效,触发器被禁用后任然存储在数据库中,只要重新启用既可以使它重新工作。

oracle提供了alter trigger语句来禁用和启用触发器

--语法格式alter trigger [<用户名方案名.>]<触发器> disable|enable;

其中:disable表示禁用触发器,enable表示启用触发器

 

触发器的删除:

--语法格式drop trigger [<用户名方案名.>]<触发器>

也可以用界面删除触发器

 

触发器 trigger

No comments:

Post a Comment