分享

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

 comeonwyj 2016-10-10

物化视图的刷新其实和普通的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

 

    本站是提供个人知识管理的网络存储空间,所有内容均由用户发布,不代表本站观点。请注意甄别内容中的联系方式、诱导购买等信息,谨防诈骗。如发现有害或侵权内容,请点击一键举报。
    转藏 分享 献花(0

    0条评论

    发表

    请遵守用户 评论公约

    类似文章 更多