本文中,我們通過實例的方法來幫助您理解物化視圖刷新過程中出現(xiàn)的約束沖突問題。 即使將物化視圖的約束建立和基表完全一致,由于物化視圖的刷新機(jī)制,也會產(chǎn)生約束沖突的現(xiàn)象。 以下是一個簡單的示例: SQL> CREATE TABLE T (ID NUMBER PRIMARY KEY, NAME VARCHAR2(30)); --表已創(chuàng)建 SQL> ALTER TABLE T ADD CONSTRAINT UN_T_NAME UNIQUE (NAME); --表已更改 SQL> CREATE MATERIALIZED VIEW LOG ON T; --實體化視圖日志已創(chuàng)建: SQL> CREATE MATERIALIZED VIEW MV_T REFRESH FAST AS SELECT * FROM T; --實體化視圖已創(chuàng)建。 SQL> ALTER TABLE MV_T ADD CONSTRAINT UN_MV_T_NAME UNIQUE (NAME); --表已更改: SQL> INSERT INTO T VALUES (1, ’A’); --已創(chuàng)建 1 行: SQL> INSERT INTO T VALUES (2, ’B’); --已創(chuàng)建 1 行: SQL> COMMIT; --提交完成: SQL> EXEC DBMS_MVIEW.REFRESH(’MV_T’) --PL/SQL 過程已成功完成。 上面構(gòu)造了一個簡單的物化視圖,物化視圖和基表建立了相同的唯一約束。 下面進(jìn)行一個循環(huán)的更新操作,然后觀察刷新的情況: 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的執(zhí)行計劃。
這種情況下,最好的解決方法是建立延遲約束。
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 過程已成功完成。
注釋:延遲唯一約束對應(yīng)的索引也必須是非唯一的,否則無法達(dá)到延遲約束的目的。
|