ORA-12054:无法为实例化视图设置ON COMMIT刷新属性

时间:2016-08-17 11:05:21

标签: sql oracle oracle11g materialized-views

我在为聚合创建物化视图时遇到问题。如果源表上出现DML,则物化视图应自动刷新并显示更新的结果。我们的想法是存储聚合结果,直接获取数字而不是查询,我基本上想看看这是否符合我们的目标。我们的表每天最多可以有300万次插入。

根据我所做的链接Example 8-3 Example 3: Creating a Materialized View

import java.awt.*;
import javax.swing.*;
import javax.swing.tree.*;

public class TreeIconTest {
  private final Icon icon = new Icon() {
    @Override public void paintIcon(Component c, Graphics g, int x, int y) {
      Graphics2D g2 = (Graphics2D) g.create();
      g2.translate(x, y);
      g2.setPaint(Color.RED);
      g2.fillRect(1, 1, getIconWidth() - 2, getIconHeight() - 2);
      g2.dispose();
    }
    @Override public int getIconWidth() {
      return 16;
    }
    @Override public int getIconHeight() {
      return 16;
    }
  };
  public JComponent makeUI() {
    JTree tree1 = new JTree();
    tree1.setEditable(true);
    tree1.setCellRenderer(new DefaultTreeCellRenderer() {
      @Override
      public Component getTreeCellRendererComponent(
          JTree tree, Object value, boolean selected, boolean expanded,
          boolean isLeaf, int row, boolean focused) {
        JLabel c = (JLabel) super.getTreeCellRendererComponent(
            tree, value, selected, expanded, isLeaf, row, focused);
        c.setIcon(icon);
        return c;
      }
    });

    JTree tree2 = new JTree();
    tree2.setEditable(true);
    DefaultTreeCellRenderer renderer2 = new DefaultTreeCellRenderer();
    renderer2.setOpenIcon(icon);
    renderer2.setClosedIcon(icon);
    renderer2.setLeafIcon(icon);
    tree2.setCellRenderer(renderer2);

    JTree tree3 = new JTree();
    tree3.setEditable(true);
    tree3.setCellRenderer(new DefaultTreeCellRenderer() {
      @Override public Icon getOpenIcon() {
        return icon;
      }
      @Override public Icon getClosedIcon() {
        return icon;
      }
      @Override public Icon getLeafIcon() {
        return icon;
      }
    });
    tree3.setCellEditor(new DefaultTreeCellEditor(
        tree3, (DefaultTreeCellRenderer) tree3.getCellRenderer()));

    JPanel p = new JPanel(new GridLayout(1, 3));
    p.add(new JScrollPane(tree1));
    p.add(new JScrollPane(tree2));
    p.add(new JScrollPane(tree3));
    return p;
  }
  public static void main(String... args) {
    EventQueue.invokeLater(() -> {
      JFrame f = new JFrame();
      f.setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE);
      f.getContentPane().add(new TreeIconTest().makeUI());
      f.setSize(320, 240);
      f.setLocationRelativeTo(null);
      f.setVisible(true);
    });
  }
}

但是这得到:

  

java.sql.SQLException:SQLException:ORA-12054:无法为实例化视图设置ON COMMIT刷新属性

1 个答案:

答案 0 :(得分:3)

该文档包括general restrictions on materialised viewmaterialised view with aggregates

虽然通过这些列表是有益的,但您可以通过检查the dbms_mview.explain_mview procedure的结果来查看现有或潜在的物化视图是否可以快速刷新:

set serveroutput on
declare
  msg_array SYS.ExplainMVArrayType;
begin
  dbms_mview.explain_mview (q'[
SELECT SUBJECTID ,count(*)as totalcount ,avg(price)as avgprice,sum(price) as totalprice
FROM your_table
WHERE SUBJECTID='xxxxx'
GROUP by SUBJECTID
]',
     msg_array);
   for i in msg_array.first..msg_array.last loop
     dbms_output.put_line(rpad(msg_array(i).capability_name, 30)
       ||' '|| msg_array(i).possible
       ||' '|| msg_array(i).msgtxt);
  end loop;
end;
/

...
REFRESH_FAST                   F 
...
REFRESH_FAST_AFTER_INSERT      F agg(expr) requires correspondng COUNT(expr) function
REFRESH_FAST_AFTER_ONETAB_DML  F SUM(expr) without COUNT(expr)
REFRESH_FAST_AFTER_ONETAB_DML  F see the reason why REFRESH_FAST_AFTER_INSERT is disabled
REFRESH_FAST_AFTER_ANY_DML     F see the reason why REFRESH_FAST_AFTER_ONETAB_DML is disabled
REFRESH_FAST_PCT               F PCT is not possible on any of the detail tables in the materialized view
...

正如@vercelli所提到的,并且正如REFRESH_FAST_AFTER_INSERT消息所示,您需要将count(*)更改为count(price)。但这不是整个故事;如果你改变了,你会看到:

REFRESH_FAST                   F 
...
REFRESH_FAST_AFTER_INSERT      F mv log does not have all necessary columns
REFRESH_FAST_AFTER_ONETAB_DML  F see the reason why REFRESH_FAST_AFTER_INSERT is disabled
REFRESH_FAST_AFTER_ONETAB_DML  F COUNT(*) is not present in the select list
REFRESH_FAST_AFTER_ANY_DML     F see the reason why REFRESH_FAST_AFTER_ONETAB_DML is disabled

您的物化视图日志必须包含您要聚合的列:

CREATE MATERIALIZED VIEW LOG ON your_table WITH SEQUENCE, ROWID
(SUBJECTID,PRICE)
INCLUDING NEW VALUES;

Materialized view LOG created.

CREATE MATERIALIZED VIEW ih_data_aggregated_view
PARALLEL 
BUILD IMMEDIATE 
REFRESH FAST ON COMMIT
AS
SELECT SUBJECTID ,count(price)as totalcount ,avg(price)as avgprice,sum(price) as totalprice
FROM your_table
WHERE SUBJECTID='xxxxx'
GROUP by SUBJECTID;

Materialized view IH_DATA_AGGREGATED_VIEW created.

仍然会报告丢失的count(*),但由于这是针对单个表的,因此不会阻止快速刷新。值得注意的是,如果您的price列可以为空,那么count(price)count(*)可能会产生不同的结果;如果是这种情况,您可能希望将两个计数都作为MV中的列。