本文通過實例的方法來幫助您理解物化視圖刷新過程中出現的約束沖突問題
即使將物化視圖的約束建立和基表完全一致由於物化視圖的刷新機制也會產生約束沖突的現象
一個簡單的例子
SQL> CREATE TABLE T (ID NUMBER PRIMARY KEY NAME VARCHAR());表已創建
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 ( A);
已創建 行
SQL> INSERT INTO T VALUES ( B);
已創建 行
SQL> COMMIT;
提交完成
SQL> EXEC DBMS_MVIEWREFRESH(MV_T)
PL/SQL 過程已成功完成
上面構造了一個簡單的物化視圖物化視圖和基表建立了相同的唯一約束
下面進行一個循環的更新操作然後觀察刷新的情況
SQL> UPDATE T SET NAME = C WHERE ID = ;
已更新 行
SQL> UPDATE T SET NAME = A WHERE ID = ;
已更新 行
SQL> UPDATE T SET NAME = B WHERE ID = ;
已更新 行
SQL> COMMIT;
提交完成
SQL> EXEC DBMS_MVIEWREFRESH(MV_T)
BEGIN DBMS_MVIEWREFRESH(MV_T); END;
*
ERROR 位於第 行:
ORA: 實體化視圖的刷新路徑中存在錯誤
ORA: 違反唯一約束條件 (YANGTKUN_MV_T_NAME)
ORA: 在SYSDBMS_SNAPSHOT line
ORA: 在SYSDBMS_SNAPSHOT line
ORA: 在SYSDBMS_SNAPSHOT line
ORA: 在line
刷新失敗了解決這個問題的一個方法是對於物化視圖不建立唯一約束唯一性由基表保證但是這種方法只對只讀物化視圖適用而且缺少唯一約束信息可能會影響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_MVIEWREFRESH(MV_T)
PL/SQL 過程已成功完成
注意延遲唯一約束對應的索引也必須是非唯一的否則無法達到延遲約束的目的
From:http://tw.wingwit.com/Article/program/Oracle/201311/18812.html