ORACLE:使用 LEFT JOIN 时物化视图不起作用
Posted
技术标签:
【中文标题】ORACLE:使用 LEFT JOIN 时物化视图不起作用【英文标题】:ORACLE : Materialized view not working when Using LEFT JOIN 【发布时间】:2010-11-21 17:30:06 【问题描述】:我想从 2 个表的 LEFT JOIN 创建一个 MATERIALIZED VIEW。但是以下给了我一个错误:
SELECT field1
FROM table_1 a
LEFT JOIN table_2 b
ON a.field1=b.field2
ORA-12054: 无法为实体化视图设置 ON COMMIT 刷新属性
但是以下工作:
SELECT field1
FROM table_1 a, table_2 b
WHERE a.field1=b.field2
有没有人知道为什么会发生这种情况。
感谢帮助
【问题讨论】:
【参考方案1】:由于这是一篇旧帖子;没有提到完整的解决方案。
-
外部联接的表应具有 Oracle 文档中提到的主键。
查询不应有任何其他约束,即不应有任何过滤条件
在
WHERE
子句中,只是连接;在SELECT
子句中也不能有CASE
/DECODE
语句;不过,GROUP BY
、SUM()
、COUNT()
等都是允许的。
在上面的示例中,如果在 dept id 列的部门表上创建主键,则查询将起作用。
【讨论】:
“WHERE 子句中不应该有任何过滤条件,只有连接” 你能支持这一点吗?【参考方案2】:要使物化视图快速刷新,有两个条件不满足。第一个是您没有指定所涉及的每个表的 rowid 列。第二个是未记录的限制:不支持 ANSI 连接。
这是一个示例,DEPT 为 table_1,别名 a,EMP 为 table_2,别名 b:
SQL> create materialized view log on emp with rowid
2 /
Materialized view log created.
SQL> create materialized view log on dept with rowid
2 /
Materialized view log created.
SQL> create materialized view empdept_mv
2 refresh fast on commit
3 as
4 select a.deptno
5 from dept a
6 left join emp b on (a.deptno = b.deptno)
7 /
from dept a
*
ERROR at line 5:
ORA-12054: cannot set the ON COMMIT refresh attribute for the materialized view
这模仿了你的情况。首先添加rowid的:
SQL> create materialized view empdept_mv
2 refresh fast on commit
3 as
4 select a.rowid dept_rowid
5 , b.rowid emp_rowid
6 , a.deptno
7 from dept a
8 left join emp b on (a.deptno = b.deptno)
9 /
from dept a
*
ERROR at line 7:
ORA-12054: cannot set the ON COMMIT refresh attribute for the materialized view
由于 ANSI 连接,它仍然无法快速刷新。转换为旧式外连接语法:
SQL> create materialized view empdept_mv
2 refresh fast on commit
3 as
4 select a.rowid dept_rowid
5 , b.rowid emp_rowid
6 , a.deptno
7 from dept a
8 , emp b
9 where a.deptno = b.deptno (+)
10 /
Materialized view created.
并证明它有效:
SQL> select * from empdept_mv
2 /
DEPT_ROWID EMP_ROWID DEPTNO
------------------ ------------------ ----------
AAARhmAAEAAAAI/AAB AAARhlAAEAAAAI3AAA 20
AAARhmAAEAAAAI/AAC AAARhlAAEAAAAI3AAB 30
AAARhmAAEAAAAI/AAC AAARhlAAEAAAAI3AAC 30
AAARhmAAEAAAAI/AAB AAARhlAAEAAAAI3AAD 20
AAARhmAAEAAAAI/AAC AAARhlAAEAAAAI3AAE 30
AAARhmAAEAAAAI/AAC AAARhlAAEAAAAI3AAF 30
AAARhmAAEAAAAI/AAA AAARhlAAEAAAAI3AAG 10
AAARhmAAEAAAAI/AAB AAARhlAAEAAAAI3AAH 20
AAARhmAAEAAAAI/AAA AAARhlAAEAAAAI3AAI 10
AAARhmAAEAAAAI/AAC AAARhlAAEAAAAI3AAJ 30
AAARhmAAEAAAAI/AAB AAARhlAAEAAAAI3AAK 20
AAARhmAAEAAAAI/AAC AAARhlAAEAAAAI3AAL 30
AAARhmAAEAAAAI/AAB AAARhlAAEAAAAI3AAM 20
AAARhmAAEAAAAI/AAA AAARhlAAEAAAAI3AAN 10
AAARhmAAEAAAAI/AAD 40
15 rows selected.
SQL> insert into dept values (50,'IT','UTRECHT')
2 /
1 row created.
SQL> commit
2 /
Commit complete.
SQL> select * from empdept_mv
2 /
DEPT_ROWID EMP_ROWID DEPTNO
------------------ ------------------ ----------
AAARhmAAEAAAAI/AAB AAARhlAAEAAAAI3AAA 20
AAARhmAAEAAAAI/AAC AAARhlAAEAAAAI3AAB 30
AAARhmAAEAAAAI/AAC AAARhlAAEAAAAI3AAC 30
AAARhmAAEAAAAI/AAB AAARhlAAEAAAAI3AAD 20
AAARhmAAEAAAAI/AAC AAARhlAAEAAAAI3AAE 30
AAARhmAAEAAAAI/AAC AAARhlAAEAAAAI3AAF 30
AAARhmAAEAAAAI/AAA AAARhlAAEAAAAI3AAG 10
AAARhmAAEAAAAI/AAB AAARhlAAEAAAAI3AAH 20
AAARhmAAEAAAAI/AAA AAARhlAAEAAAAI3AAI 10
AAARhmAAEAAAAI/AAC AAARhlAAEAAAAI3AAJ 30
AAARhmAAEAAAAI/AAB AAARhlAAEAAAAI3AAK 20
AAARhmAAEAAAAI/AAC AAARhlAAEAAAAI3AAL 30
AAARhmAAEAAAAI/AAB AAARhlAAEAAAAI3AAM 20
AAARhmAAEAAAAI/AAA AAARhlAAEAAAAI3AAN 10
AAARhmAAEAAAAI/AAD 40
AAARhmAAEAAAAI7AAA 50
16 rows selected.
this blogpost 的第 6 点提到了 ANSI 连接语法限制。
问候, 抢。
【讨论】:
非常感谢罗。这非常有帮助:) 虽然我必须使用旧样式进行左连接(将不得不重写许多视图和查询),但这让我很恼火。丹 不敢相信 Oracle 还没有实现 ANSI JOIN 支持。谢谢你【参考方案3】:按照以下说明使 DBMS_MVIEW.EXPLAIN_MVIEW 工作: http://www.sqlsnippets.com/en/topic-12884.html
能够:
REFRESH_COMPLETE
没有能力:
REFRESH_FAST
REFRESH_FAST_AFTER_INSERT 此类型 MV 不支持 FROM 列表中的内联视图或子查询
REFRESH_FAST_AFTER_INSERT 此类型 MV 不支持 FROM 列表中的内联视图或子查询
REFRESH_FAST_AFTER_INSERT 从列表中查看或子查询
REFRESH_FAST_AFTER_ONETAB_DML 查看 REFRESH_FAST_AFTER_INSERT 被禁用的原因
MV_REPORT
REFRESH_FAST_AFTER_ANY_DML 查看 REFRESH_FAST_AFTER_ONETAB_DML 被禁用的原因
【讨论】:
以上是关于ORACLE:使用 LEFT JOIN 时物化视图不起作用的主要内容,如果未能解决你的问题,请参考以下文章