您的位置:首页 > 数据库 > Oracle

oracle技术之oracle利用触发器对物化视图刷新进行定制

2013-05-15 10:48 477 查看
物化视图的刷新其实和普通的SQL执行没有什么本质的区别,因此也可以通过在物化视图上创建触发器的方式,对刷新操作进行定制。

正好前两天有人在BLOG上问我,如果在物化视图添加一个时间戳列,并在物化视图更新的时候,自动维护这个列。其实很简单,通过触发器就可以达到这个目的:
SQL> CREATE TABLE T (ID NUMBER PRIMARY KEY, NAME VARCHAR2(30));

表已创建。

SQL> INSERT INTO T SELECT ROWNUM, TNAME FROM TAB;

已创建25行。

SQL> COMMIT;

提交完成。

SQL> CREATE MATERIALIZED VIEW LOG ON T;

实体化视图日志已创建。

SQL> CREATE TABLE MV_T (ID NUMBER, NAME VARCHAR2(30), TIME DATE DEFAULT SYSDATE);

表已创建。

SQL> CREATE MATERIALIZED VIEW MV_T ON PREBUILT TABLE REFRESH FAST

2 AS SELECT * FROM T;

实体化视图已创建。

SQL> ALTER SESSION SET NLS_DATE_FORMAT = 'YYYY-MM-DD HH24:MI:SS';

会话已更改。

SQL> SELECT * FROM T WHERE ID = 1;

ID NAME

---------- ------------------------------

1 T_AB

SQL> SELECT * FROM MV_T WHERE ID = 1;

未选定行

SQL> EXEC DBMS_MVIEW.REFRESH('MV_T', 'C')

PL/SQL过程已成功完成。

SQL> SELECT * FROM MV_T WHERE ID = 1;

ID NAME TIME

---------- ------------------------------ -------------------

1 T_AB 2009-06-21 00:05:09

SQL> UPDATE T SET NAME = 'A' WHERE ID = 1;

已更新1行。

SQL> COMMIT;

提交完成。

SQL> EXEC DBMS_MVIEW.REFRESH('MV_T', 'F')

PL/SQL过程已成功完成。

SQL> SELECT * FROM MV_T WHERE ID = 1;

ID NAME TIME

---------- ------------------------------ -------------------

1 A 2009-06-21 00:05:09

在这个例子中建立一个ON PREBUILT TABLE类型的物化视图,其中物化视图的基表比主表要多了一个字段,并为这个字段设置了默认值。
物化视图在完全刷新的时候会自动在这个字段中写入默认值,但是如果基表进行了更新操作,则物化视图中新增的时间戳字段并不会在刷新的时候自动更新。
其实解决这个问题的方法很简单,一个UPDATE触发器就可以了:
SQL> CREATE OR REPLACE TRIGGER MV_T

2 BEFORE UPDATE ON MV_T

3 FOR EACH ROW

4 BEGIN

5 :NEW.TIME := SYSDATE;

6 END;

7 /

触发器已创建

SQL> UPDATE T SET NAME = 'B' WHERE ID = 1;

已更新1行。

SQL> COMMIT;

提交完成。

SQL> SELECT * FROM MV_T WHERE ID = 1;

ID NAME TIME

---------- ------------------------------ -------------------

1 A 2009-06-21 00:05:09

SQL> EXEC DBMS_MVIEW.REFRESH('MV_T', 'F')

PL/SQL过程已成功完成。

SQL> SELECT * FROM MV_T WHERE ID = 1;

ID NAME TIME

---------- ------------------------------ -------------------

1 B 2009-06-21 00:14:01

只需要处理UPDATE操作就可以了,因为DELETE不涉及到这个问题,而INSERT操作由于表的时间戳字段设置了默认值,因此不需要触发器进行额外的设置:
SQL> INSERT INTO T VALUES (26, 'C');

已创建1行。

SQL> EXEC DBMS_MVIEW.REFRESH('MV_T', 'F')

PL/SQL过程已成功完成。

SQL> SELECT * FROM MV_T WHERE ID = 26;

ID NAME TIME

---------- ------------------------------ -------------------

26 C 2009-06-21 00:14:42

oracle视频教程请关注:http://u.youku.com/user_video/id_UMzAzMjkxMjE2.html
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息