没有合适的资源?快使用搜索试试~ 我知道了~
资源推荐
资源详情
资源评论
65
- 65 -
第八章 触发器
触发器是许多关系数据库系统都提供的一项技术。在 ORACLE 系统里,触发器类似过
程和函数,都有声明,执行和异常处理过程的 PL/SQL 块。
§8.1 触发器类型
触发器在数据库里以独立的对象存储,它与存储过程不同的是,存储过程通过其它程序
来启动运行或直接启动运行,而触发器是由一个事件来启动运行。即触发器是当某个事件发
生时自动地隐式运行。并且,触发器不能接收参数。所以运行触发器就叫触发或点火(firing)。
ORACLE 事件指的是对数据库的表进行的 INSERT、UPDATE 及 DELETE 操作或对视图进
行类似的操作。ORACLE 将触发器的功能扩展到了触发 ORACLE,如数据库的启动与关闭
等。
§8.1.1 DML 触发器
ORACLE 可以在DML 语句进行触发,可以在DML 操作前或操作后进行触发,并且可
以对每个行或语句操作上进行触发。
§8.1.2 替代触发器
由于在 ORACLE 里,不能直接对由两个以上的表建立的视图进行操作。所以给出了替
代触发器。它就是 ORACLE 8 专门为进行视图操作的一种处理方法。
§8.1.3 系统触发器
ORACLE 8i 提供了第三种类型的触发器叫系统触发器。它可以在 ORACLE 数据库系
统的事件中进行触发,如ORACLE 系统的启动与关闭等。
触发器组成:
触发事件:即在何种情况下触发 TRIGGER; 例如:INSERT, UPDATE, DELETE。
触发时间:即该 TRIGGER 是在触发事件发生之前(BEFORE)还是之后(AFTER)触
发,也就是触发事件和该 TRIGGER 的操作顺序。
触发器本身:即该 TRIGGER 被触发之后的目的和意图,正是触发器本身要做的事情。
例如:PL/SQL 块。
触发频率:说明触发器内定义的动作被执行的次数。即语句级(STATEMENT)触发器和
行级(ROW)触发器。
语句级(STATEMENT)触发器:是指当某触发事件发生时,该触发器只执行一次;
行级(ROW)触发器:是指当某触发事件发生时,对受到该操作影响的每一行数据,触
发器都单独执行一次。
66
- 66 -
§8.2 创建触发器
创建触发器的一般语法是:
CREATE [OR REPLACE] TRIGGER trigger_name
{BEFORE | AFTER }
{INSERT | DELETE | UPDATE [OF column [, column …]]}
ON [schema.] table_name
[REFERENCING {OLD [AS] old | NEW [AS] new| PARENT as parent}]
[FOR EACH ROW ]
[WHEN condition]
trigger_body;
其中:
BEFORE 和 AFTER 指出触发器的触发时序分别为前触发和后触发方式,前触发是在
执行触发事件之前触发当前所创建的触发器,后触发是在执行触发事件之后触发当前所创建
的触发器。
FOR EACH ROW 选项说明触发器为行触发器。行触发器和语句触发器的区别表现在:
行触发器要求当一个 DML 语句操作影响数据库中的多行数据时,对于其中的每个数据行,
只要它们符合触发约束条件,均激活一次触发器;而语句触发器将整个语句操作作为触发事
件,当它符合约束条件时,激活一次触发器。当省略 FOR EACH ROW 选项时,BEFORE
和 AFTER 触发器为语句触发器,而 INSTEAD OF 触发器则为行触发器。
REFERENCING 子句说明相关名称,在行触发器的 PL/SQL 块 和 WHEN 子句中可以
使用相关名称参照当前的新、旧列值,默认的相关名称分别为 OLD 和 NEW。触发器的
PL/SQL 块中应用相关名称时,必须在它们之前加冒号(:),但在 WHEN 子句中则不能加冒
号。
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
67
- 67 -
AFTER UPDATE
AFTER UPDATE FOR EACH ROW
BEFORE DELETE
BEFORE DELETE FOR EACH ROW
AFTER DELETE
AFTER DELETE FOR EACH ROW
§8.2.1 触发器触发次序
1. 执行 BEFORE 语句级触发器;
2. 对与受语句影响的每一行:
执行 BEFORE 行级触发器
执行 DML 语句
执行 AFTER 行级触发器
3. 执行 AFTER 语句级触发器
§8.2.2 创建 DML 触发器
触发器名与过程名和包的名字不一样,它是单独的名字空间,因而触发器名可以和表或
过程有相同的名字,但在一个模式中触发器名不能相同。
触发器的限制
CREATE TRIGGER 语句文本的字符长度不能超过 32KB;
触发器体内的SELECT 语句只能为SELECT … INTO …结构,或者为定义游标所使用
的 SELECT 语句。
触发器中不能使用数据库事务控制语句 COMMIT; ROLLBACK, SVAEPOINT 语句;
由触发器所调用的过程或函数也不能使用数据库事务控制语句;
触发器中不能使用 LONG, LONG RAW 类型;
触发器内可以参照 LOB 类型列的列值,但不能通过 :NEW 修改 LOB 列中的数据;
问题:当触发器被触发时,要使用被插入、更新或删除的记录中的列值,有时要使用操作前、后列
的值.
实现: :NEW 修饰符访问操作完成后列的值
:OLD 修饰符访问操作完成前列的值
特性
INSERT
UPDATE
DELETE
OLD
NULL
有效
有效
NEW
有效
有效
NULL
例 1: 建立一个触发器, 当职工表 emp 表被删除一条记录时,把被删除记录写到职工表删
除日志表中去。
CREATE TABLE emp_his AS SELECT * FROM EMP WHERE 1=2;
CREATE OR REPLACE TRIGGER del_emp
68
- 68 -
BEFORE DELETE ON scott.emp FOR EACH ROW
BEGIN
-- 将修改前数据插入到日志记录表 del_emp ,以供监督使用。
INSERT INTO emp_his(deptno , empno, ename , job ,mgr , sal , comm , hiredate )
VALUES( :old.deptno, :old.empno, :old.ename , :old.job,
:old.mgr, :old.sal, :old.comm, :old.hiredate );
END;
DELETE emp WHERE empno=7788;
DROP TABLE emp_his;
DROP TRIGGER del_emp;
§8.2.3 创建替代(INSTEAD OF)触发器
创建触发器的一般语法是:
CREATE [OR REPLACE] TRIGGER trigger_name
INSTEAD OF
{INSERT | DELETE | UPDATE [OF column [, column …]]}
ON [schema.] view_name
[REFERENCING {OLD [AS] old | NEW [AS] new| PARENT as parent}]
[FOR EACH ROW ]
[WHEN condition]
trigger_body;
其中:
BEFORE 和 AFTER 指出触发器的触发时序分别为前触发和后触发方式,前触发是在
执行触发事件之前触发当前所创建的触发器,后触发是在执行触发事件之后触发当前所创建
的触发器。
INSTEAD OF 选项使 ORACLE 激活触发器,而不执行触发事件。只能对视图和对象
视图建立 INSTEAD OF 触发器,而不能对表、模式和数据库建立INSTEAD OF 触发器。
FOR EACH ROW 选项说明触发器为行触发器。行触发器和语句触发器的区别表现在:
行触发器要求当一个 DML 语句操走影响数据库中的多行数据时,对于其中的每个数据行,
只要它们符合触发约束条件,均激活一次触发器;而语句触发器将整个语句操作作为触发事
件,当它符合约束条件时,激活一次触发器。当省略 FOR EACH ROW 选项时,BEFORE
和 AFTER 触发器为语句触发器,而 INSTEAD OF 触发器则为行触发器。
REFERENCING 子句说明相关名称,在行触发器的 PL/SQL 块 和 WHEN 子句中可以
使用相关名称参照当前的新、旧列值,默认的相关名称分别为 OLD 和 NEW。触发器的
PL/SQL 块中应用相关名称时,必须在它们之前加冒号(:),但在 WHEN 子句中则不能加冒
号。
WHEN 子句说明触发约束条件。Condition 为一个逻辑表达时,其中必须包含相关名
称,而不能包含查询语句,也不能调用PL/SQL 函数。WHEN 子句指定的触发约束条件只
能用在 BEFORE 和 AFTER 行触发器中,不能用在 INSTEAD OF 行触发器和其它类型的
69
- 69 -
触发器中。
INSTEAD_OF 用于对视图的DML 触发,由于视图有可能是由多个表进行联结(join)而
成,因而并非是所有的联结都是可更新的。但可以按照所需的方式执行更新,例如下面情况:
CREATE OR REPLACE VIEW emp_view AS
SELECT deptno, count(*) total_employeer, sum(sal) total_salary
FROM emp GROUP BY deptno;
在此视图中直接删除是非法:
SQL>DELETE FROM emp_view WHERE deptno=10;
DELETE FROM emp_view WHERE deptno=10
*
ERROR 位于第 1 行:
ORA-01732: 此视图的数据操纵操作非法
但是我们可以创建INSTEAD_OF 触发器来为 DELETE 操作执行所需的处理,即删除 EMP
表中所有基准行:
CREATE OR REPLACE TRIGGER emp_view_delete
INSTEAD OF DELETE ON emp_view FOR EACH ROW
BEGIN
DELETE FROM emp WHERE deptno= :old.deptno;
END emp_view_delete;
DELETE FROM emp_view WHERE deptno=10;
DROP TRIGGER emp_view_delete;
DROP VIEW emp_view;
§8.2.3 创建系统事件触发器
ORACLE8i 提供的系统事件触发器可以在 DDL 或数据库系统上被触发。DDL 指的是数
据定义语言,如CREATE 、ALTER 及 DROP 等。而数据库系统事件包括数据库服务器的
启动或关闭,用户的登录与退出、数据库服务错误等。创建系统触发器的语法如下:
创建触发器的一般语法是:
CREATE OR REPLACE TRIGGER [sachema.] trigger_name
{BEFORE|AFTER}
{ddl_event_list | database_event_list}
ON { DATABASE | [schema.] SCHEMA }
[WHEN_clause]
trigger_body;
剩余20页未读,继续阅读
资源评论
小小哭包
- 粉丝: 1899
- 资源: 3854
上传资源 快速赚钱
- 我的内容管理 展开
- 我的资源 快来上传第一个资源
- 我的收益 登录查看自己的收益
- 我的积分 登录查看自己的积分
- 我的C币 登录后查看C币余额
- 我的收藏
- 我的下载
- 下载帮助
安全验证
文档复制为VIP权益,开通VIP直接复制
信息提交成功