第八章理论课触发器和内置程序包
- 格式:pdf
- 大小:667.16 KB
- 文档页数:17
《Oracle数据库应用 》理论课
触发器和内置程序包
本章技能目标
理解和应用触发器
了解内置程序包
1. 触发器
触发器是特定事件出现的时候,自动执行的代码块。类似于存储过程,触发器与存储过程的区
别在于:存储过程是由用户或应用程序显式调用的,而触发器是不能被直接调用的。
触发器可以用于加载Oracle的默认功能,提供高度可定制的数据库,触发器能够执行的功
能有:
1、 允许/限制对表的修改
2、 自动生成派生列,比如自增字段
3、 强制数据一致性
4、 提供审计和日志记录
5、 防止无效的事务处理
6、 启用复杂的业务逻辑
触发器与特定的表或视图相关联,用于检查对表或视图所做的数据修改。无论正在执行操作的
用户身份如何,触发器都能够在它们执行操作时生效。当INSERT,DELETE,UPADTE等事件
发生在表或视图中时,就会激活触发器的代码。 用于创建触发器的语法为:
CREATE [OR REPLACE] TRIGGER trigger_name AFTER | BEFORE | INSTEAD OF [INSERT] [[OR] UPDATE [OF column_list]] [[OR] DELETE] ON table_or_view_name [REFERENCING {OLD [AS] old / NEW [AS] new}] [FOR EACH ROW] [WHEN (condition)] pl/sql_block;
其中: 第8章 触发器和内置程序包
- 2
– before和after:指在事件发生之前或之后激活触发器。
instead of:如果使用此子句,表示可以执行触发器代码来代替导致触发器调用的事件。
insert、delete和update:指定构成触发器事件的数据操纵类型,update还可以制定列的列表。
referencing:指定新行(即将更新)和旧行(更新前)的其他名称,默认为new和old。
table_or_view_name:指要创建触发器的表或视图的名称。
for each row:指定是否对受影响的每行都执行触发器,即行级触发器,如果不使用此子句,则
为语句级触发器。
when:限制执行触发器的条件,该条件可以包括新旧数据值得检查。
declare---end:是一个标准的PL/SQL块。
例1演示如何在SCOTT模式的EMP表上创建触发器。
例1: CREATE OR REPLACE TRIGGER biu_emp_deptno BEFORE INSERT OR UPDATE OF deptno ON emp FOR EACH ROW WHEN (New.deptno <> 40) BEGIN :New.comm := 0; END; /
提示:如果创建触发器时出现错误,请使用SHOW ERRORS命令查看详细的错误信息。
1.1 触发器的组成部分
触发器由三部分组成:
触发器语句(事件)
定义激活触发器的 DML 事件和 DDL 事件
触发器限制
执行触发器的条件,该条件必须为真才能激活触发器
触发器操作(主体)
包含一些 SQL 语句和代码,它们在发出了触发器语句且触发限制的值为真时运
行
触发器语句
触发器语句是那些可以导致触发器的事件,即在表或视图上执行的INSERT,DELETE,UPADTE
之类的DML语句,在模式对象上执行的DDL语句或数据库事件。
在例1触发器中,第2行至第四行,如下代码所示,构成了触发器语句。
BEFORE INSERT OR UPDATE OF deptno ON emp FOR EACH ROW
这就是说,触发器会在这些事件之前隐式执行:当对EMP表执行INSERT语句时或对EMP表
的deptno列进行UPADTE时。而且触发器将在受到影响的每一行上执行一次。
但是触发器是否真正的执行还要检查触发器的条件,只有满足限制条件才会执行。
触发器限制
触发器限制条件包含一个布尔表达式,该值必须为“真”才能激活触发器。如果该值为“假”第8章 触发器和内置程序包
- 3
– 或“未知”,将不运行触发器操作。 例1中的触发器的限制如下面的代码所示。
WHEN (New.deptno <> 40)
这就是说,如果列deptno的新值不等于40,触发器将会执行。
触发器操作
触发器操作是触发器的主体,包含一些SQL语句和代码。这些代码在执行触发器语句且触发器
限制条件的值为“真”时运行。行级触发器允许触发操作中的语句访问行的列值。
例1中的触发器操作如下面的代码所示 BEGIN :New.comm := 0; END;
以上这段代码将列comm新增设置为0。
现在,来测试此触发器产生的效果。例2演示了如何在EMP表中插入记录。
例2: INSERT INTO emp ( EMPNO, ENAME, JOB, MGR, HIREDATE, SAL, COMM, DEPTNO)
VALUES ( 8000, 'Jack', 'ANALYST', NULL, '31-12月-2003', 5000, 600, 20);
INSERT INTO emp ( EMPNO, ENAME, JOB, MGR, HIREDATE, SAL, COMM, DEPTNO)
VALUES ( 8001, 'Fred', 'MANAGER', NULL, '31-12月-2002', 6000, 500, 40);
COMMIT;
上述语句在EMP表中插入了两条记录。并为每行记录指定了COMM列的值。用户在表中插入
了值,这将激活前面创建的触发器。
现在,通过下面的命令查看实际插入到表中的数据。
SELECT ename, sal, comm, deptno FROM emp WHERE empno>=8000;
上述语句的输出结果是:
ENAME SAL COMM DEPTNO
---------- --------- --------- ------
Jack 5000.00 0.00 20
Fred 6000.00 500.00 40
可以看到,插入第一行数据时指定了COMM列的值为600。但是DEPTNO的值不等于40,所
以会激活触发器,COMM列的值被设置为0。插入第二行记录时,由于DEPTNO的值等于40,
不满足触发器限制条件,所以触发器不执行,用户指定的COMM列的值插入到数据库中。
1.2 触发器类型
Oracle具有不同类型的触发器,可以实现不同的任务。这些触发器类型包括:
语句触发器,行触发器,INSTEAD OF 触发器,模式触发器,数据库级触发器
分类如下图: 第8章 触发器和内置程序包
- 4
–
DDL 触发器:在模式中执行 DDL 语句时执行
数据库级触发器:在发生打开、关闭、登录和退出数据库等系统事件时执行
DML 触发器:在对表或视图执行DML语句时执行
语句级触发器:无论受影响的行数是多少,都只执行一次
行级触发器:对DML语句修改的每个行执行一次
INSTEAD OF 触发器:用于用户不能直接使用 DML 语句修改的视图
具体叙述如下:
1. 行级触发器
行级触发器对DML语句影响的每个行执行一次,例如:UPADTE语句影响多行,就会对每行
都激活一次触发器。行触发器是触发器中最常用的一种。通常用于数据库审计和实现复杂的业
务逻辑。可以在CREATE TRIGGER命令中指定FOR EACH ROW子句创建行级触发器。
由于触发器是事件驱动的,因此可以设置触发器在这些事件之前或之后执行,即在执行DML
语句之前或之后执行。在触发器中,可以引用DML语句中涉及的旧值和新值。“新”是指由
DML语句创建的数据值(如插入记录中的列)。
执行DML语句之前的值的默认名称是 :old ,之后的值是 :new。
insert 操作只有:new
delete 操作只有 :old
update 操作两者都有
如果需要通过触发器在插入行中设置一个列值,就应该使用BEFORE INSERT 触发器访问新值。
使用AFTER INSERT不允许设置插入值,因为该行已经插入表中。
在审计应用程序中经常使用AFTER行级触发器,直到行被修改才会触发它们。行的成功修改表
明此行已经通过该表定义的完整性约束。
例3演示了行级触发器的应用。
例3: CREATE TABLE TEST_TRG (ID NUMBER, NAME VARCHAR2(20)); CREATE SEQUENCE SEQ_TEST; CREATE OR REPLACE TRIGGER BI_TEST_TRG BEFORE INSERT OR UPDATE OF ID ON TEST_TRG FOR EACH ROW BEGIN IF INSERTING THEN 第8章 触发器和内置程序包
- 5 – SELECT SEQ_TEST.NEXTVAL INTO :NEW.ID FROM DUAL; ELSE
RAISE_APPLICATION_ERROR(-20020, '不允许更新ID值!');
END IF; END; / INSERT INTO TEST_TRG VALUES (0, 'First row'); INSERT INTO TEST_TRG VALUES (0, 'Second row'); INSERT INTO TEST_TRG VALUES (0, 'Third row'); COMMIT;
例3先创建一个测试表TEST_TRG,接着创建一个序列SEQ_TEST,然后创建一个触发器自动生成ID列的值,并禁止UPADTE表的ID列。最后,向测试表中插入3条记录。现在,使用以
下语句查看表中的数据。
SELECT * FROM TEST_TRG;
上述语句的输出结果是:
ID NAME
---------- --------------------
1 First row
2 Second row
3 Third row
可以看出,表的ID列的值是由触发器自动产生的,而不是用户在插入命令中指定值。
提示:如果一个触发器由多种语句的触发,可以使用INSERTING,UPDATING,DELETING
条件谓词来检查,如果值为“真”,那么就是相应得语句类型激活了该触发器。条件谓词只能在
触发器主体中引用。
begin if inserting then ----- elsif updating then ----- elsif deleting then ------ end if; end; if updating(‘COL1’) or updating(‘COL2’) then ------ end if;
2. 语句级触发器
语句级触发器对每个DML语句执行一次。例如,如果一条INSERT语句在表中插入200行,
那么这个表上的INSERT语句级触发器只执行一次。语句级触发器不常用于与数据库相关的活
动,通常用于强制实施在表 上执行操作的额外安全性措施。语句级触发器是CREATE