11.2.5 复合类型触发器

复合类型的触发器是Oracle 11g的新特性,属于触发器的增强部分。复合类型的触发器相当于在一个触发器中包含了4种不同类型的触发器,分别是语句之前(before statement)、行之前(before row)、行之后(after row)、语句之后(after statement)。这么做可以很轻松地把变量在各状态之间传递,而在该类型触发器出现之前,变量在触发器之间的传递比较麻烦。

利用该类型的触发器还可以方便地解决ORA-04091错误,这里涉及一个变异表的概念,读者可以理解变异表是正在被DML操作修改的表,也是触发器的作用表。而触发器通常不能对变异表进行操作,下面一个示例将利用复合类型的触发器,解决ORA-04091错误。

【示例10】复合型触发器

该触发器试图实现功能:当为PRODUCTINFO表中的数据提高价格时,触发器判断新旧价格差是否高于价格在2000以下的所有产品价格的平均值的20%,如果高于此值,则提示数据有问题。相关步骤如下:

1)创建普通类型的触发器,并激发,查看是否存在ORA-04091错误。具体脚本如下:


01 CREATE TRIGGER PRIC_TGR

02 AFTER UPDATE ON PRODUCTINFO

03 FOR EACH ROW

04 DECLARE

05 V_PRO_AVG NUMBER(10,2):=0.0;

06 BEGIN

07 SELECT AVG(PRODUCTPRICE)

08 INTO V_PRO_AVG

09 FROM PRODUCTINFO

10 WHERE PRODUCTINFO.PRODUCTPRICE<2000;

11

12 IF:NEW.PRODUCTPRICE-:OLD.PRODUCTPRICE>V_PRO_AVG*0.20 THEN

13 RAISE_APPLICATION_ERROR(-20001,'数据修改错误!');

14 END IF;

15 END;


【代码解析】

❑第1~3行表示创建作用于表PRODUCT INFO上的修改后的行级触发器,名为PRIC_TGR。

❑第7~10行表示求取价格在2000以下的产品的平均价格,并存入变量V_PRO_AVG中,这种SELECT INTO形式的语句会把触发表作为变异表。

❑第12~14行判断新增价格如果高于平均价格的20%,则提示出错。

【验证触发器】

该触发器创建完成后,执行如下语句:


UPDATE PRODUCTINFO

SET PRODUCTPRICE=PRODUCTPRICE+300

WHERE PRODUCTPRICE>2000;


执行效果见图11.12。

11.2.5 复合类型触发器 - 图1

图 11.12 修改表出现ORA-04091错误

2)创建复合类型的触发器,解决上一步出现的错误。具体脚本如下:


01 CREATE OR REPLACE TRIGGER COMPOUND_TGR

02 FOR UPDATE ON PRODUCTINFO COMPOUND TRIGGER

03

04 V_PRO_AVG NUMBER(10,2):=0.0;

05

06 BEFORE STATEMENT IS

07 BEGIN

08 SELECT AVG(PRODUCTPRICE)

09 INTO V_PRO_AVG

10 FROM PRODUCTINFO

11 WHERE PRODUCTINFO.PRODUCTPRICE<2000;

12 END BEFORE STATEMENT;

13

14 AFTER EACH ROW IS

15 BEGIN

16 IF:NEW.PRODUCTPRICE-:OLD.PRODUCTPRICE>V_PRO_AVG*0.20 THEN

17 RAISE_APPLICATION_ERROR(-20011,'数据修改错误!');

18 END IF;

19 END AFTER EACH ROW;

20 END;

21 /


【代码解析】

❑第1~2行表示创建复合类型的触发器,触发事件为UPDATE操作。

❑第4行表示声明变量,存放平均价格。

❑第6~12行表示前语句触发的脚本。此时的操作相当于前语句触发器的操作。

❑第14~19行表示后行级的触发。也就是说,它的执行次数和修改的记录数一致。

【验证触发器】

该触发器创建完成后,执行如下语句:


UPDATE PRODUCTINFO

SET PRODUCTPRICE=PRODUCTPRICE+300

WHERE PRODUCTPRICE>2000;


执行效果见图11.13。

11.2.5 复合类型触发器 - 图2

图 11.13 复合触发器验证结果

从图11.13中可以看出该触发器已经正常激发,避免了普通触发器出现的ORA-04091错误。以后读者就可以不用费神地解决此类错误了。