触发器
触发器时存储在数据库中的过程,当某些事件发生时这个过程就会出发,即事件发生后过程自动执行。
一般的,当数据库中的表或视图发生插入、删除、修改时,触发器就能执行PL/SQL块。Oracle8i后,也支持PL/SQL语句和java程序的执行。
触发器类似过程和函数,但必须存储在数据库中且不能被块进行本地化声明。触发器不接受参数。
触发器可做:
1.维护不可能在创建表时通过声明性约束进行的复杂的完整性约束限制。
2.通过记录所进行的修改以及谁进行了修改来审计表中的信息。
3.当表被修改时,自动给其他需要执行操作的程序发信号。
作用:
1.安全性:
1.基于数据库的值使用户具有操作数据库的某种特权。
2.基于时间限制用户的操作。
3.基于数据库中的数据限制用户的操作。
2.审计
1.可跟踪用户对数据库的操作
2.审计用户操作数据库的语句
3.把用户对数据库的更新写入审计表中
4.实现非标准的数据完整性检查和约束。
3.实现复杂的非标准的数据哭的相关完整性规则
4.自动计算数据值
触发器组成:
1.触发触发器的事件
2.发生事件的对象
3.可触发器体选的控制触发器何时触发的条件
4.在触发器被触发时执行的触发器体
触发器体是一个包含SQL语句和PL/SQL语句的过程调用或PL/SQL块,过程调用或是一个PL/SQL,或是一个被封装在PL/SQL块中的java程序。
若触发条件为真,并且触发器语句已经输入,则触发器体中的语句将被执行。
能创建被以下语句触发的触发器:
1.DML(insert、update、delete)
2.DDL(create、alter、drop)
3.数据库操作(servererror,logon,logoff,startup,shutdown)
触发器可创建在下列对象上:
1.数据库表
2.数据库视图
3.用户模式
4.数据库实例
根据创建语句及所对应的对象分类:
1.DML触发器:作用在数据库表上的有DML语句触发的触发器
2.系统触发器:是对数据库实例或某个用户模式进行操作的触发器。又可分为:数据库级触发器和模式级触发器。
3.替代触发器:视图用于对视图更新的触发器。
触发器的创建语句:create trigger (用于创建任何触发器)
行触发器:就是行只要受到影响就触发一次。
语句级触发器:执行了相应的语句才会被触发。
1.DML触发器:一种可以在表上定义的传统触发器。
一般触发DML触发器的DML语句有:insert(插入)、update(更新)、delete(删除)
在创建触发器中要明确规定before/after选项,该选项规定触发器中的SQL语句执行的动机。
DML触发器可以是记录级触发器或语句级触发器。
记录级触发器为每条受触发的SQL语句执行一次,而语句级触发器只执行一次。
只有记录中级触发器才能访问受影响的记录中的数据值,语句级触发器不能被访问。
DML语句被执行时就出发触发器,下面是指定DML语句的顺序:
1.执行before语句级触发器
2.对于受语句影响的每一行:
1.执行before语句级触发器
2.执行DML语句
3.执行after语句级触发器
3.执行after语句级触发器
1.DML触发器的创建:
create or replace [schema.]trigger
{before|after} ver_list on 表名
[referncing{old as old}|{new as new}|{parent as parent}]
[for each row][when (condition)]
PL/SQL_block|call_procedure
schema:触发器所在的模式
before|after:该触发器在动作事件发生前触发还是在发生后触发。
ver_list:是DML语句。即:delete、insert、update。可用or或and连接多个。
on 表名:指定触发器创建在哪个表上。
referncing:这一行允许在PL/SQL块或when条件中指定别名。
for each row:指定当oracle进行delete、update、insert时,不论一条语句改变了多少记录,oracle对每条记录触发一次触发器。它决定了时行触发器,还是语句级触发器。
when :指定触发器约束。when只能用在行触发器。若对某一行的为真,那么触发器体所包含的语句被执行,并应用那一行数据。若为假,则触发器体所包含的语句不会执行。
PL/SQL_block:指定触发器触发后oracle执行的程序块。
call_procedure:该语句允许调用存储过程,而不是指定触发器代码。
行触发器的触发器体有一些特定的结构能被包括在PL/SQL块中,相关的名称和referencing选项,条件谓语inserting、deleting、updating。
条件谓语不能用于过程调用,只能用于PL/SQL块中的触发器体。
例子:
create or replace trigger print
before delete or insert or update on emp
for each row
declare
sa_diff number;
begin
sa_diff:=new.sal-:old.sal;
Dbms_output.put_line('old sa:'||:old.sal);
end;
2.访问行触发器中的列值
在行触发器体内,PL/SQL代码和SQL语句都可访问触发器语句所影响的行的旧值和新值。
对于表被修改的每一列,都有两个相关的名称存在,一个对应旧值,一个对应新值。
若触发器被insert触发只有访问新值才有意义。旧值为空。
before或after行被update触发,新值旧值都能访问。
delete触发,则访问旧值才有意义,新值为空。
新的列值通过在列名前使用new表示符来引用,旧的列值能通过在列名前使用old表示符来引用。
例子:if:new.sal > 1000
if:new.sal < :old.sal
3.条件谓语
在触发器体中想使用条件判断,用条件谓语。
例子:
...
insert or update on emp
...
if inserting then ... end if;(若触发的语句是insert则执行此条件语句中的代码)
if updating then ... end if;
2.系统触发器:数据库级触发级、用户模式级触发器。
要创建数据库级触发器要有Administrator data base trigger 的系统权限,一般只有管理员有。
1.创建系统触发器:
create or replace triggre [schema.]触发器名
[before|after]
{ddl_event[or ddl_event...]|database_event[or database_event...]}
on {[schema.]schema|database}
[when (condition)]
PL/SQL_block|call_procedure
ddl_event:指定造成触发器触发的DDL事件。该时间指定为数据库或模式上的事件。如:alteranalyze、create、drop、rename等。
database_event:指定造成触发器触发的特定数据库状态。对于每一个这样的触发事件,oracle打开一个匿名的事务,触发触发器,提交任何独立的事务,这些事件有:servererror、logon、lonoff、startup、shutdown等。
schema:指定在schema定义在模式上的触发器。
database:指定database定义在数据库上的触发器。
when:触发器约束条件
PL/SQL_block:指定触发器触发后oracle执行的程序块。
call_procedure:该语句允许调用存储过程,而不是指定触发器代码。
3.替代触发器:instead of触发器
他提供了一种修改视图实例的方法,可在客户端通过OCI调用来实现。要修改一个可修改的对象视图实例,必须定义一个instead of触发器。
触发该触发器时,不是去执行触发语句,而是直接在相关的表上执行update、insert、dalete语句。
注意事项:
1.instead of 触发器只能被创建在视图上。
2.被创建在视图上的触发器都不能加before|after选项
3.当instead of 触发器对视图进行insert或update操作时,check选项不是必须的,但instead of触发器体必须执行检查。
4.instead of 触发器只能在行级触发。
1.创建替代触发器
crate or replace trigger [schema.]触发器名
instead of ver_list on [schema.]视图名
[refercening{old as old}|{new as new}|{parent as parent}]
[for each row][when (conndition)]
PL/SQL_block|call_procedure
schenma:触发器所在的模式
instead of:指定该触发器为instead of触发器
on 试图名:指定触发器作用在视图上
referncening:运行在PL/SQL块上或when条件中指定别名
for each row:指定为行触发器,还是语句级触发器。
when:触发约束条件
PL/SQL_block:指定触发器触发后oracle执行的程序块。
call_procedure:该语句允许调用存储过程,而不是指定触发器代码。
注意:
1.若视图中有以下结构则不能使用update、insert、delete语句:
1.set操作符
2.group函数
3.group by、connect by或start with 条件
4.distinct操作符
2.若一个视图中包含伪列或函数,那么在update该视图时,update语句中不能包括位列或函数。