(注:主要摘自尚硅谷oracle教程笔记)
触发器是许多关系数据系统都提供的一项技术。在 ORACLE 系统里,触发器类似过程和函数,都有声明,执行和异常处理过程的 PL/SQL 块
触发器类型
触发器在数据库里以独立的对象存储,它与存储过程不同的是,存储过程通过其他程序来启动运行或者直接启动运行,而触发器是由一个事件来启动运行。即触发器是当某个事件发生时自动地隐式运行。并且,触发器不能接收参数。所以运行触发器就叫触发或点火。ORACLE 事件指的是对数据库的表进行的 INSERT、UPDATE 及DELETE 操作或对视图进行类似的操作。 ORACLE 将触发器的功能扩展到 触发 ORACLE,如数据库的启动与关闭等
触发器的组成:
创建触发器
CREATE [OR REPLACE] TRIGGER Trigger_name
{BEFORE | AFTER}
{INSERT | DELETE | UPDATE [OF column...]}
ON [schema.]table_name
[FOR EACH ROW]
[WHEN condition]
trigger_body;
其中:BEFORE 和 AFTER 指出触发器的触发时序分别为前触发和后触发方式,前触发是在执行触发事件之前触发当前所创建的触发器,后触发器是在执行触发事件之后触发当前所创建的触发器。
FOR EACH ROW 选项说明触发器为行触发器。行触发器和语句触发器的区别表现在:行触发器要求当一个 DML 语句操作影响数据中的多行数据时,对于其中的每个数据行,只要它们符合触发约束条件,均激活一次出触发器;而语句触发器将整个语句操作作为触发事件,当它符合约束条件时,激活一次触发器。
WHEN 子句说明触发约束条件。Condition 为一个逻辑表达式时,其中必须包含相关名称,而不能包含查询语句,也不能调用 PL/SQL 函数。 WHEN 子句指定的触发约束条件只能用 BEFORE 和 AFTER 行触发器中,不能用在 INSTEAD OF 行触发器和其他类型的触发器中。
当触发器被触发时,要使用被插入、更新或删除的记录中的列值,有时要使用操作前、后的值
实现:
:NEW 修饰符访问操作完成后列的值
:OLD 修饰符访问操作完成前列的值
示例
一个helloworld级别的触发器
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;
触发器的 helloworld: 编写一个触发器, 在向 emp 表中插入记录时, 打印 'helloworld’
create or replace trigger emp_trigger
after
insert on emp
for each row
begin
dbms_output.put_line('helloworld');
end;
行级触发器: 每更新 employees 表中的一条记录, 都会导致触发器执行
create or replace trigger employees_trigger
after
update on employees
for each row
begin
dbms_output.put_line('修改了一条记录!');
end;
语句级触发器: 一个 update/delete/insert 语句只使触发器执行一次
create or replace trigger employees_trigger
after
update on employees
begin
dbms_output.put_line('修改了一条记录!');
end;
使用 :new, :old 修饰符
create or replace trigger employees_trigger
after
update on employees
for each row
begin
dbms_output.put_line('old salary: '
|| :old.salary || ', new salary: ' || :new.salary);
end;
编写一个触发器, 在对 my_emp 记录进行删除的时候, 在 my_emp_bak 表中备份对应的记录
create or replace trigger bak_emp_trigger
before delete on my_emp
for each row
begin
insert into my_emp_bak values(
:old.id, :old.name, :old.sal);
end;