PL/SQL 触发器
①触发器类型
触发器在数据库里以独立的对象存储,它与存储过程不同的是,存储过程通过其它程序来启动运行或直接启动运行,而触发器是由一个事件来启动运行。
即触发器是当某个事件发生时自动地隐式运行。并且,触发器不能接收参数。所以运行触发器就叫触发或点火(firing)。
ORACLE事件指的是对数据库的表进行的INSERT、UPDATE及DELETE操作或对视图进行类似的操作。
ORACLE将触发器的功能扩展到了触发ORACLE,如数据库的启动与关闭等。
1.DML触发器
ORACLE可以在DML语句进行触发,可以在DML操作前或操作后进行触发,并且可以对每个行或语句操作上进行触发。
2.替代触发器
由于在ORACLE里,不能直接对由两个以上的表建立的视图进行操作。所以给出了替代触发器。
3.系统触发器
它可以在ORACLE数据库系统的事件中进行触发,如ORACLE系统的启动与关闭等。
②触发器组成:?
?触发事件:即在何种情况下触发TRIGGER; 例如:INSERT, UPDATE, DELETE。
?触发时间:即该TRIGGER 是在触发事件发生之前(BEFORE)还是之后(AFTER)触发,也就是触发事件和该TRIGGER 的操作顺序。
?触发器本身:即该TRIGGER 被触发之后的目的和意图,正是触发器本身要做的事情。例如:PL/SQL 块。
?触发频率:说明触发器内定义的动作被执行的次数。即语句级(STATEMENT)触发器和行级(ROW)触发器。
? ? ? 语句级(STATEMENT)触发器:是指当某触发事件发生时,该触发器只执行一次;
? ? ? 行级(ROW)触发器:是指当某触发事件发生时,对受到该操作影响的每一行数据,触发器都单独执行一次。
③创建触发器
创建触发器的一般语法是:
CREATE[OR REPLACE] TRIGGER trigger_name
? ? {BEFORE| AFTER}
? ? {INSERT| DELETE| UPDATE[OF column [, column …]]}
? ? ON[schema.] table_name
? ? [FOR EACH ROW]
? ? [WHEN condition]
? ? begin
? ? ? ? trigger_body;
? ? end;
其中:
? ? BEFORE 和AFTER指出触发器的触发时序分别为前触发和后触发方式,
? ? ? ? 前触发是在执行触发事件之前触发当前所创建的触发器,后触发是在执行触发事件之后触发当前所创建的触发器。
? ? FOR EACH ROW选项说明触发器为行触发器。
? ? ? ? 行触发器和语句触发器的区别表现在:行触发器要求当一个DML语句操做影响数据库中的多行数据时,对于其中的每个数据行,
?只要它们符合触发约束条件,均激活一次触发器;
?而语句触发器将整个语句操作作为触发事件,当它符合约束条件时,激活一次触发器。
?当省略FOR EACH ROW 选项时,BEFORE和AFTER触发器为语句触发器,而INSTEAD OF 触发器则为行触发器。
? ? WHEN 子句说明触发约束条件。Condition 为一个逻辑表达时,其中必须包含相关名称,而不能包含查询语句,也不能调用PL/SQL 函数。
? ? ? ? WHEN 子句指定的触发约束条件只能用在BEFORE 和AFTER 行触发器中,不能用在INSTEAD OF 行触发器和其它类型的触发器中。
? ? 当一个基表被修改( INSERT, UPDATE, DELETE)时要执行的存储过程,执行时根据其所依附的基表改动而自动触发,因此与应用程序无关,
? ? 用数据库触发器可以保证数据的一致性和完整性。
每张表最多可建立12种类型的触发器,它们是:
? ? BEFORE INSERT
? ? BEFORE INSERT FOR EACH ROW
? ? AFTER INSERT
? ? AFTER INSERT FOR EACH ROW
? ? BEFORE UPDATE
? ? BEFORE UPDATE FOR EACH ROW
? ? AFTER UPDATE
? ? AFTER UPDATE FOR EACH ROW
? ? BEFORE DELETE
? ? BEFORE DELETE FOR EACH ROW
? ? AFTERDELETE
? ? AFTER DELETE FOR EACH ROW
④触发器触发次序
1. 执行BEFORE语句级触发器;
2. 对与受语句影响的每一行:
? 执行BEFORE行级触发器
? 执行DML语句
? 执行AFTER行级触发器
3. 执行AFTER语句级触发器
⑤创建DML触发器
触发器名可以和表或过程有相同的名字,但在一个模式中触发器名不能相同。
触发器的限制
? CREATE TRIGGER语句文本的字符长度不能超过32KB;
? 触发器体内的SELECT 语句只能为SELECT … INTO …结构,或者为定义游标所使用的SELECT 语句。
? 触发器中不能使用数据库事务控制语句COMMIT; ROLLBACK, SVAEPOINT 语句;
? 由触发器所调用的过程或函数也不能使用数据库事务控制语句;
问题:当触发器被触发时,要使用被插入、更新或删除的记录中的列值,有时要使用操作前、后列的值.
实现:? :NEW? 修饰符访问操作完成后列的值
? ? ? :OLD? 修饰符访问操作完成前列的值
特性 INSERT UPDATE DELETE
OLD NULL 有效 有效
NEW 有效 有效 NULL
[例]
create or replace trigger hello_trigger
after
update on employees
for each row
begin
? ? dbms_output.put_line('hello...');
? ? dbms_output.put_line('old.salary:'|| :OLD.salary||',new.salary'||:NEW.salary);
end;
然后执行:update employees set salary = salary + 1000;
⑥创建替代(INSTEAD OF)触发器
创建触发器的一般语法是:
CREATE [OR REPLACE] TRIGGER trigger_name
? ? INSTEAD OF
? ? {INSERT | DELETE | UPDATE [OFcolumn [, column …]]}
? ? ON[schema.] view_name
? ? [FOR EACH ROW]
? ? [WHENcondition]
? ? begin
? ? ? ? trigger_body;
? ? end;
其中:
? ? INSTEAD OF 选项使ORACLE激活触发器,而不执行触发事件。
? ? 只能对视图和对象视图建立INSTEAD OF触发器,而不能对表、模式和数据库建立INSTEAD OF 触发器。
? ? FOR EACH ROW选项说明触发器为行触发器。
? ? ? ? 行触发器和语句触发器的区别表现在:行触发器要求当一个DML语句操做影响数据库中的多行数据时,对于其中的每个数据行,只要它们符合触发约束条件,均激活一次触发器;
? ? ? ? 而语句触发器将整个语句操作作为触发事件,当它符合约束条件时,激活一次触发器。
? ? ? ? 当省略FOR EACH ROW 选项时,BEFORE 和AFTER 触发器为语句触发器,而INSTEAD OF 触发器则为行触发器。
? ? WHEN 子句说明触发约束条件。Condition 为一个逻辑表达时,其中必须包含相关名称,而不能包含查询语句,也不能调用PL/SQL 函数。
? ? ? ? WHEN 子句指定的触发约束条件只能用在BEFORE 和AFTER 行触发器中,不能用在INSTEAD OF 行触发器