物化视图的刷新其实和普通的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 实体化视图已创建。 SQL> ALTER SESSION SET NLS_DATE_FORMAT = 'YYYY-MM-DD HH24:MI:SS'; 会话已更改。 SQL> SELECT * FROM T WHERE ID = 1; ID NAME 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 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 在这个例子中建立一个ON PREBUILT TABLE类型的物化视图,其中物化视图的基表比主表要多了一个字段,并为这个字段设置了默认值。 物化视图在完全刷新的时候会自动在这个字段中写入默认值,但是如果基表进行了更新操作,则物化视图中新增的时间戳字段并不会在刷新的时候自动更新。 其实解决这个问题的方法很简单,一个UPDATE触发器就可以了: SQL> CREATE OR REPLACE TRIGGER MV_T 触发器已创建 SQL> UPDATE T SET NAME = 'B' WHERE ID = 1; 已更新 1 行。 SQL> COMMIT; 提交完成。 SQL> SELECT * FROM MV_T WHERE ID = 1; ID NAME TIME SQL> EXEC DBMS_MVIEW.REFRESH('MV_T', 'F') PL/SQL 过程已成功完成。 SQL> SELECT * FROM MV_T WHERE ID = 1; ID NAME TIME 只需要处理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
|
|