物化视图刷新过程中出现的约束冲突问题

转载自:http://yangtingkun.itpub.net/post/468/286875

即使将物化视图的约束建立和基表完全一致,由于物化视图的刷新机制(Oracle在刷新物化视图的时候没有保证更新的顺序),也会产生约束冲突的现象。

一个简单的例子:

SQL> CREATE TABLE T (ID NUMBER PRIMARY KEY, NAME VARCHAR2(30));

表已创建。

SQL> ALTER TABLE T ADD CONSTRAINT UN_T_NAME UNIQUE (NAME);

表已更改。

SQL> CREATE MATERIALIZED VIEW LOG ON T;

实体化视图日志已创建。

SQL> CREATE MATERIALIZED VIEW MV_T REFRESH FAST AS SELECT * FROM T;

实体化视图已创建。

SQL> ALTER TABLE MV_T ADD CONSTRAINT UN_MV_T_NAME UNIQUE (NAME);

表已更改。

SQL> INSERT INTO T VALUES (1, 'A');

已创建 1 行。

SQL> INSERT INTO T VALUES (2, 'B');

已创建 1 行。

SQL> COMMIT;

提交完成。

SQL> EXEC DBMS_MVIEW.REFRESH('MV_T')

PL/SQL 过程已成功完成。

上面构造了一个简单的物化视图,物化视图和基表建立了相同的唯一约束。

下面进行一个循环的更新操作,然后观察刷新的情况:

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

已更新 1 行。

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

已更新 1 行。

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

已更新 1 行。

SQL> COMMIT;

提交完成。

SQL> EXEC DBMS_MVIEW.REFRESH('MV_T')
BEGIN DBMS_MVIEW.REFRESH('MV_T'); END;

*
ERROR 位于第 1 行:
ORA-12008: 实体化视图的刷新路径中存在错误
ORA-00001: 违反唯一约束条件 (YANGTK.UN_MV_T_NAME)
ORA-06512: 在"SYS.DBMS_SNAPSHOT", line 794
ORA-06512: 在"SYS.DBMS_SNAPSHOT", line 851
ORA-06512: 在"SYS.DBMS_SNAPSHOT", line 832
ORA-06512: 在line 1

刷新失败了。解决这个问题的一个方法是对于物化视图不建立唯一约束,唯一性由基表保证。但是这种方法只对只读物化视图适用。而且,缺少唯一约束信息,可能会影响SQL的执行计划。

这种情况下,最好的解决方法是建立延迟约束。

SQL> ALTER TABLE MV_T DROP CONSTRAINT UN_MV_T_NAME;

表已更改。

SQL> ALTER TABLE MV_T ADD CONSTRAINT UN_MV_T_NAME UNIQUE (NAME) DEFERRABLE;

表已更改。

SQL> EXEC DBMS_MVIEW.REFRESH('MV_T')

PL/SQL 过程已成功完成。

注意,延迟唯一约束对应的索引也必须是非唯一的(如果是唯一索引,延迟约束将没有意义),否则无法达到延迟约束的目的。

About this Entry

This page contains a single entry by Sky published on October 23, 2007 1:59 PM.

Oracle 10g New Features was the previous entry in this blog.

物化视图日志结构 is the next entry in this blog.

Find recent content on the main index or look in the archives to find all content.