Oracle PL/SQL 触发器(trigger)学习笔记(二)

2014-11-24 17:42:59 · 作者: · 浏览: 2
果在行级触发器的定义中给出了WHEN子句,触发器主体就只对满足WHEN所定义条件的那些记录行执行。WHEN子句的基本形式如下:


WHEN trigger_condition


其中,trigger_condition是一个布尔表达式。每处理一行记录,都会重新判断该表达式的值。


也可以在trigger_condition内部使用:new和:old记录,但是与REFERENCING子句一样,在trigger_condition内部使用:new和:old时,不需要冒号。仅在触发器主体中才需要使用冒号。


5、触发器谓词


可以在触发器内部使用3个布尔函数,判断触发该触发器的到底是什么操作。这3个谓词分别是INSERTING、UPDATING和DELETING.


使用方法如下面这个例子所示


view plaincopy to clipboardprint


CREATE OR REPLACE TRIGGER LogInventoryChanges


BEFORE INSERT OR DELETE OR UPDATE ON inventory


FOR EACH ROW


DECLARE


v_ChangeType CHAR(1);


BEGIN


/* Use 'I' for an INSERT, 'D' for DELETE, and 'U' for UPDATE. */


IF INSERTING THEN


v_ChangeType := 'I';


ELSIF UPDATING THEN


v_ChangeType := 'U';


ELSE


v_ChangeType := 'D';


END IF;


/* Record all the changes made to inventory in


inventory_audit. Use SYSDATE to generate the timestamp, and


USER to return the userid of the current user. */


INSERT INTO inventory_audit


(change_type, changed_by, timestamp,


old_isbn, old_status, old_status_date, old_amount,


new_isbn, new_status, new_status_date, new_amount)


VALUES


(v_ChangeType, USER, SYSDATE,


:old.isbn, :old.status, :old.status_date, :old.amount,


:new.isbn, :new.status, :new.status_date, :new.amount);


END LogInventoryChanges;


/


CREATE OR REPLACE TRIGGER LogInventoryChanges


BEFORE INSERT OR DELETE OR UPDATE ON inventory


FOR EACH ROW


DECLARE


v_ChangeType CHAR(1);


BEGIN


/* Use 'I' for an INSERT, 'D' for DELETE, and 'U' for UPDATE. */


IF INSERTING THEN


v_ChangeType := 'I';


ELSIF UPDATING THEN


v_ChangeType := 'U';


ELSE


v_ChangeType := 'D';


END IF;


/* Record all the changes made to inventory in


inventory_audit. Use SYSDATE to generate the timestamp, and


USER to return the userid of the current user. */


INSERT INTO inventory_audit


(change_type, changed_by, timestamp,


old_isbn, old_status, old_status_date, old_amount,


new_isbn, new_status, new_status_date, new_amount)


VALUES


(v_ChangeType, USER, SYSDATE,


:old.isbn, :old.status, :old.status_date, :old.amount,


:new.isbn, :new.status, :new.status_date, :new.amount);


END LogInventoryChanges;


/


6、INSTEAD-OF触发器


INSTEAD-OF触发器仅可以定义在视图上(关系型的或对象),并且它们可以替代点火它们的DML语句进行点火。INSTEAD-OF触发器必须是行级的。


7、触发器的限制


触发器的主体是一个PL/SQL块。在PL/SQL块中可以使用的所有语句在触发器主体中都是合法的,但是要受到下面限制的约束:


触发器不应该使用事务控制语句—COMMIT、ROLLBACK或SAVEPOINT。触发器作为触发语句执行的一部分被点火,它和触发语句在同一个事务中。当触发语句被提交或撤回提交时,触发器的工作也相应被提交会撤回提交。


由触发器主体调用的任何过程和函数都不能使用事务控制语句。


触发器主体不能声明任何LONG或者LONG RAW变量。而且,:new和:old不能指向定义触发器的表中的LONG和LONG RAW列。


触发器主体可以访问的表有所限制。


触发器P-Code


当包或者子程序存储在数据字典中时,存储的除了该对象的源代码还有经过编译的p-code。但是对于触发器来说就不是这样的。在数据字典中唯一存储的是触发器的源代码,而不是p-code。结果,每次当从数据字典中重新读出触发器时,必须要进行编译。这对触发器的定义和使用的方式不会带来什么影响,但是会影响触发器的性能。


8、系统触发器


我们前面所看到的DML触发器和INSTEAD-OF触发器都是基于DML事件。而另一方面,系统触发器的激活则是基于两种不同的事件:DDL事件或数据库事件。DDL事件包括CREATE、ALTER或DROP语句,而数据库事件包括数据库服务器的启动/关闭事件,用户的登陆/断开事件,以及服务器错误。创建系统触发器的语法如下:


view plaincopy to clipboardprint


CREATE [OR REPLACE] TRIGGER [schema.]trigger_name


{BEFORE | AFTER}


{ddl_event_list | database_event_list}


ON {DATABASE | [schema.]SCHEMA}


[when_clause]


Trigger_body;


CREATE [OR REPLACE] TRIGGER [schema.]trigger_name


{BEFORE | AFTER}


{ddl_event_list | database_event_list}


ON {DATABASE | [schema.]SCHEMA}


[when_clause]


Trigger_body;


其中,ddl_event_list是由OR关键字隔开的一个或 个DDL事件,database_event_list则是由OR关键字隔开的一个或多个数据库事件。


注意:不能创建INSTEAD-OF系统级触发器。


通过子句ON {DATABASE | [schema.]SCHEMA}我们可以指定这个系统触发器是定义在数据库级上还是模式级上。只要发生了激活事件,数据库