首先,不幸的是,Oracle 物化视图不允许使用 ANSI 连接语法,请使用旧的 Oracle 连接语法。 It is a bug in Oracle i believe so
我将用我的答案展示的任何内容都只是关于使用 FAST REFRESH 选项实现的物化
回到您最初的问题,我们是否可以在物化视图中使用具有增量刷新功能的普通视图:
答案是否
话虽如此,如果我们尝试将导致错误并且无法创建它,如下所示,
表结构:(仅用于演示示例,不用于实际的规范化表
CREATE TABLE emp(emp_id NUMBER primary key
,empname VARCHAR2(1000));
CREATE TABLE address_details(address_id NUMBER primary key
,address_text VARCHAR2(1000)
,emp_id NUMBER);
CREATE TABLE salary_details(sal_id NUMBER primary key
,salary NUMBER
,emp_id NUMBER);
物化视图日志:
--drop statements
DROP MATERIALIZED VIEW LOG ON emp;
DROP MATERIALIZED VIEW LOG ON address_details;
DROP MATERIALIZED VIEW LOG ON salary_details;
--create statements
--default
CREATE MATERIALIZED VIEW LOG ON emp;
CREATE MATERIALIZED VIEW LOG ON address_details;
CREATE MATERIALIZED VIEW LOG ON salary_details;
--with primary key (same as default above but I would stick to mention it explicitly for understanding and versioning (svn or git) purpose
CREATE MATERIALIZED VIEW LOG ON emp WITH PRIMARY KEY;
CREATE MATERIALIZED VIEW LOG ON address_details WITH PRIMARY KEY;
CREATE MATERIALIZED VIEW LOG ON salary_details WITH PRIMARY KEY;
--with primary key and rowid
CREATE MATERIALIZED VIEW log ON emp WITH PRIMARY KEY, ROWID;
CREATE MATERIALIZED VIEW log ON address_details WITH PRIMARY KEY, ROWID;
CREATE MATERIALIZED VIEW log ON salary_details WITH PRIMARY KEY, ROWID;
1.首先尝试根据需要创建具有普通视图的 MV:
CREATE OR REPLACE VIEW DETAILS_VIEW AS
SELECT sal_id
,salary
,address_id
,address_text
,sl.emp_id
--,sl.rowid sl_rowid
--,ad.rowid ad_rowid
FROM salary_details sl
,address_details ad
WHERE sl.emp_id = ad.emp_id;
DROP MATERIALIZED VIEW emp_mview;
CREATE MATERIALIZED VIEW EMP_MVIEW
REFRESH FORCE ON COMMIT
AS
SELECT emp.emp_id
,emp.empname
,dv.sal_id
,dv.salary
,dv.address_id
,dv.address_text
--,emp.rowid emp_rowid
--,dv.sl_rowid
--,dv.ad_rowid
FROM emp emp
,details_view dv
WHERE emp.emp_id = dv.emp_id(+);
结果:
ORA-12054: cannot set the ON COMMIT refresh attribute for the materialized view
相信我,我已经尝试过使用主键和 rowid 创建日志并将 rowid 添加到 select 子句的所有方案,但没有任何效果
前进:
2.第二次尝试通过将所有单个基表放在 from 子句中来使用来自 oracle 的标准连接创建 MV:
我已经创建了带有选项主键的物化视图日志,正如我在上面的物化视图日志部分中提到的那样。
CREATE MATERIALIZED VIEW EMP_MVIEW
REFRESH FORCE ON COMMIT
AS
SELECT emp.emp_id
,emp.empname
,sl.sal_id
,sl.salary
,ad.address_id
,ad.address_text
FROM emp emp
,salary_details sl
,address_details ad
WHERE emp.emp_id = sl.emp_id(+)
AND emp.emp_id = ad.emp_id(+);
宾果游戏:Materialized view created ,
但是,等等……这是否意味着我现在可以做一个 FAST REFRESH ?让我们检查一下:
我们可以使用DBMS_MVIEW.EXPLAIN_MVIEW 分析物化视图功能,它将功能详细信息插入到名为MV_CAPABILITIES_TABLE 的表中(可用于@ $ORACLE_HOME/rdbms/admin/utlxmv.sql)。如果我们没有来自 DBA 的脚本和授权,您需要获得它。不过我还是会给出下面的脚本
如何分析 MV 的能力:
--table structure
CREATE TABLE mv_capabilities_table (
statement_id VARCHAR2(30),
mvowner VARCHAR2(30),
mvname VARCHAR2(30),
capability_name VARCHAR2(30),
possible CHAR(1),
related_text VARCHAR2(2000),
related_num NUMBER,
msgno INTEGER,
msgtxt VARCHAR2(2000),
seq NUMBER
);
--delete always before analyzing for a view to have only rows for a specific and not to have where clause to filter :)
DELETE FROM mv_capabilities_table;
--run this script which will analyze and insert into mv_capabilities_table
BEGIN
dbms_mview.explain_mview('EMP_MVIEW');
END;
/
/***ANALYSIS RESULT:***/
--I am intersted only with data related to FAST REFRESH category
SELECT capability_name
,possible
,substr(msgtxt
,1
,60) AS msgtxt
FROM mv_capabilities_table
WHERE capability_name LIKE '%FAST%';
/**
CAPABILITY_NAME POSSIBLE MSGTXT
REFRESH_FAST N
REFRESH_FAST_AFTER_INSERT N the SELECT list does not have the rowids of all the detail t
REFRESH_FAST_AFTER_INSERT N mv log must have ROWID
REFRESH_FAST_AFTER_INSERT N mv log must have ROWID
REFRESH_FAST_AFTER_INSERT N mv log must have ROWID
REFRESH_FAST_AFTER_ONETAB_DML N see the reason why REFRESH_FAST_AFTER_INSERT is disabled
REFRESH_FAST_AFTER_ANY_DML N see the reason why REFRESH_FAST_AFTER_ONETAB_DML is disabled
REFRESH_FAST_PCT N PCT FAST REFRESH is not possible if query contains LEFT OUTE
**/
如果您查看带有文本**mv log must have ROWID**上面的分析结果告诉我们物化视图日志缺少ROWID 选项,因此FAST REFRESH 是不可能的。
注意:mv_capabilities_table 中的其他列也会告诉你我没有包含的确切表格,你可以自己检查和测试看看。
前进..
3.第三次尝试使用来自 oracle 的标准连接和包含选项 ROWID 的 MV 日志创建 MV:
步骤:(不再提供脚本,只提供模拟步骤
- 我将删除并使用选项
ROWID 重新创建 MV 日志,如上面 物化视图日志部分所述。
- 然后我将删除并重新创建我在第二次尝试中使用的相同的 MV 定义,最终将创建
- 接下来我将尝试重复如何分析 MV 的能力部分中所述的步骤来分析 MV
我在分析报告中得到了什么:
/**
CAPABILITY_NAME POSSIBLE MSGTXT
REFRESH_FAST N
REFRESH_FAST_AFTER_INSERT N the SELECT list does not have the rowids of all the detail t
REFRESH_FAST_AFTER_ONETAB_DML N see the reason why REFRESH_FAST_AFTER_INSERT is disabled
REFRESH_FAST_AFTER_ANY_DML N see the reason why REFRESH_FAST_AFTER_ONETAB_DML is disabled
REFRESH_FAST_PCT N PCT FAST REFRESH is not possible if query contains LEFT OUTE
**/
Ufffff:我真的很累,MV 还没有FAST REFRESH 的能力,原因告诉我们"the SELECT list does not have the rowids of all the detail tables"
含义:FAST REFRESH 的下一个条件是Rowids of all the tables in the FROM list must appear in the SELECT list of the query
所以,
4.第四次也是最后一次尝试使用来自 oracle 的标准连接和包含选项 ROWID 的 MV 日志创建 MV,并且详细信息表 rowid 现在包含在 select 子句中:
步骤:
- 与第 3 次尝试一样,第一次刷新所需的 MV 日志已就位,我将删除并再次重新创建 MV,但这次添加了详细表的 rowid。
MV最终脚本:
CREATE MATERIALIZED VIEW EMP_MVIEW
REFRESH FORCE ON COMMIT
AS
SELECT emp.emp_id
,emp.empname
,sl.sal_id
,sl.salary
,ad.address_id
,ad.address_text
,emp.rowid emp_rowid
,sl.rowid sl_rowid
,ad.rowid ad_rowid
FROM emp emp
,salary_details sl
,address_details ad
WHERE emp.emp_id = sl.emp_id(+)
AND emp.emp_id = ad.emp_id(+);
现在,随着 MV 的创建,让我们再分析一下如何分析 MV 的能力部分中描述的 MV 的能力。 (手指交叉)
结果:
SELECT capability_name
,possible
,substr(msgtxt,1,60) AS msgtxt
FROM mv_capabilities_table
WHERE capability_name LIKE '%FAST%';
/**
CAPABILITY_NAME POSSIBLE MSGTXT
REFRESH_FAST Y
REFRESH_FAST_AFTER_INSERT Y
REFRESH_FAST_AFTER_ONETAB_DML Y
REFRESH_FAST_AFTER_ANY_DML Y
REFRESH_FAST_PCT N PCT FAST REFRESH is not possible if query contains LEFT OUTE
**/
终于REFRESH_FAST 功能成为可能,正如我们所看到的POSSIBLE -> Y
对不起,回答太长了,但我想我应该把我过去在 MV 中学到的东西写出来,这可能对分享有用。
我发现一些对于 Oracle 物化视图总是有用的链接:
干杯!!