物化视图的刷新其实和普通的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
本文URL地址:http://www.bianceng.cn/database/Oracle/201410/45472.htm
在这个例子中建立一个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