Oracle物化视图错误:包含代码

Posted

技术标签:

【中文标题】Oracle物化视图错误:包含代码【英文标题】:Oracle materialized view error: code included 【发布时间】:2011-11-20 17:23:01 【问题描述】:

当我在 Oracle 10g 上运行以下代码时:

drop materialized view test4;
drop materialized view test3;
drop table test2;
drop table test1;

create table test1
(
  x1 varchar2(1000),
  constraint test1_pk primary key (x1)
);

create materialized view log on test1 with sequence;

create table test2
(
  x2 varchar2(1000),
  constraint test2_pk primary key (x2)
);

create materialized view log on test2 with sequence;

create materialized view test3
refresh complete on demand 
as
(
  select x1 from test1
  union all
  select null from dual where 0 = 1
);

alter table test3 add constraint test3_pk primary key (x1);

create materialized view log on test3 with sequence;

create materialized view test4
refresh fast on commit
as
(
  select t1.rowid as rid1, t2.rowid as rid2, t1.x1 u1, t2.x2
  from test3 t1, test2 t2
  where t1.x1 = t2.x2
);

我在尝试创建物化视图test4 时收到此错误:

SQL Error: ORA-12053: this is not a valid nested materialized view  
12053. 00000 -  "this is not a valid nested materialized view"  
*Cause:    The list of objects in the FROM clause of the definition of this  
           materialized view had some dependencies upon each other.  
*Action:   Refer to the documentation to see which types of nesting are valid.

我不明白“FROM 子句”中的任何对象如何相互依赖。

如何让它工作?目前我能想到的唯一解决方法是将test3替换为普通表并手动删除和刷新数据。这种方法行得通,但似乎有点 hack。

或者(也许最好)我只想看一个示例,其中可以有两个表,并将它们加入一个物化视图,其中一个基表是批量更新的(并且不需要反映在物化视图),但其他更新应反映在物化视图中(即它是“一半”fast refresh on commit 和一半complete refresh on demand)。我尝试使用refresh force,但是当使用EXECUTE DBMS_MVIEW.EXPLAIN_MVIEW() 时,我发现没有证据表明提交时刷新刷新可用。我也想用union alls 来做这件事。

【问题讨论】:

+1 更好地解释,现在说明:) test3 没有多大意义:select null from dual where 0 = 1 永远不会返回一行。 @Allan:这是一种将其整合为聚合的技巧。如果它停止错误,请随意删除它。 @Clinton:只是为了清楚起见:在数据库术语中,复合查询具有 union 语句(或任何其他集合运算符);聚合查询有一个group by 子句。在这里没有太大区别,但它可能会使 Oracle 文档更有意义。 【参考方案1】:

您可以像这样使 test4 物化视图快速刷新:

SQL> create table test1
  2  ( x1 varchar2(1000)
  3  , constraint test1_pk primary key (x1)
  4  )
  5  /

Table created.

SQL> create materialized view log on test1 with rowid
  2  /

Materialized view log created.

SQL> create table test2
  2  ( x2 varchar2(1000)
  3  , constraint test2_pk primary key (x2)
  4  )
  5  /

Table created.

SQL> create materialized view log on test2 with rowid
  2  /

Materialized view log created.

SQL> create materialized view test4
  2  refresh fast on commit
  3  as
  4    select t1.rowid as rid1
  5         , t2.rowid as rid2
  6         , t1.x1 u1
  7         , t2.x2
  8      from test1 t1
  9         , test2 t2
 10     where t1.x1 = t2.x2
 11  /

Materialized view created.

SQL> insert into test1 values ('hello')
  2  /

1 row created.

SQL> insert into test2 values ('hello')
  2  /

1 row created.

SQL> commit
  2  /

Commit complete.

SQL> select * from test4
  2  /

RID1               RID2
------------------ ------------------
U1
---------------------------------------------
X2
---------------------------------------------
AAATU5AAEAAAssfAAA AAATU8AAEAAAssvAAA
hello
hello


1 row selected.

您的情况不起作用,因为要使嵌套 MV 起作用,基础 MV 不能是基本 MV。起初这听起来很奇怪,但您需要像使用 test3 一样的技巧才能使其工作。此外,要使连接 MV 起作用,需要创建基础表的物化视图日志 WITH ROWID。

您可能想查看我写的关于快速可刷新物化视图错误的一系列博客文章。它们描述了几乎所有的限制:

Basic MV'sJoin MV'sAggregate MV'sUnion all MV'sNested MV'sMV_CAPABILITIES_TABLESummary

问候, 抢。


添加:2011 年 9 月 29 日

这是一个嵌套 MV 的示例,它也在 test2 上使用了 union all 技巧:

SQL> create table test1
  2  ( x1 varchar2(1000)
  3  , constraint test1_pk primary key (x1)
  4  )
  5  /

Table created.

SQL> create materialized view log on test1 with rowid
  2  /

Materialized view log created.

SQL> create table test2
  2  ( x2 varchar2(1000)
  3  , constraint test2_pk primary key (x2)
  4  )
  5  /

Table created.

SQL> create materialized view log on test2 with rowid
  2  /

Materialized view log created.

SQL> create materialized view test2_mv
  2  refresh fast on commit
  3  as
  4  select rowid rid
  5       , x2
  6       , 'A' umarker
  7    from test2
  8   union all
  9  select rowid
 10       , x2
 11       , 'B'
 12    from test2
 13   where 1=0
 14  /

Materialized view created.

SQL> alter table test2_mv add constraint test2_mv_pk primary key(x2)
  2  /

Table altered.

SQL> create materialized view log on test2_mv with rowid
  2  /

Materialized view log created.

SQL> create materialized view test3
  2  refresh fast on commit
  3  as
  4  select rowid rid
  5       , x1
  6       , 'A' umarker
  7    from test1
  8   union all
  9  select rowid
 10       , x1
 11       , 'B'
 12    from test1
 13   where 0 = 1
 14  /

Materialized view created.

SQL> alter table test3 add constraint test3_pk primary key (x1)
  2  /

Table altered.

SQL> create materialized view log on test3 with rowid
  2  /

Materialized view log created.

SQL> create materialized view test4
  2  refresh fast on commit
  3  as
  4    select t1.rowid as rid1
  5         , t2.rowid as rid2
  6         , t1.x1 u1
  7         , t2.x2
  8      from test3 t1
  9         , test2_mv t2
 10     where t1.x1 = t2.x2
 11  /

Materialized view created.

SQL> insert into test1 values ('hello')
  2  /

1 row created.

SQL> insert into test2 values ('hello')
  2  /

1 row created.

SQL> commit
  2  /

Commit complete.

SQL> select * from test4
  2  /

RID1               RID2
------------------ ------------------
U1
---------------------------------------------------
X2
---------------------------------------------------
AAATXbAAEAAAstdAAA AAATXXAAEAAAstNAAA
hello
hello


1 row selected.

希望这会有所帮助!

【讨论】:

“一开始这听起来很奇怪,但你需要一个像 test3 一样的技巧才能让它工作”:你的回答只给出了基于两个表的物化视图的代码,我可以已经做了。您能否给我一些示例代码,让我可以将快速刷新视图建立在完全按需刷新视图的基础上? 解决方案取决于您的完整刷新视图的外观。它是基本的、连接的、聚合的、联合的还是嵌套的 MV?在您的示例中,不需要 test3 MV。 或者你的 test3 MV 不是作为一个技巧来使它成为一个联合所有 MV 而不是一个基本的 MV,我想知道...... 可以说test3 是基于不能快速刷新的复杂事物(不仅仅是这个简单示例中的test2)。我目前正在将test3 实现为表,并执行delete * from test3insert into test3 ( complicated SQL or view ) 来更新它。当然,我可以在这个批量更新的表上建立一个快速可刷新的视图。我想将此test3 改为物化视图,因此我不必对其执行删除...插入循环(这是物化视图在刷新时无论如何都应该执行的操作) 这是可能的,但它可能会导致 MV 在 MV 之上在 MV 之上等等。嵌套 MV 的限制之一是底层 MV 不能是基本 MV。在您的情况下,您的 test2 MV 是基本的,所以它不起作用。如果你让 test2 成为一个联合所有 MV,就像你对 test3 所做的那样,那么它会起作用。如果您仍然遇到问题,可以将其添加到您的问题中吗?【参考方案2】:

引用Oracle

使用多层实体化视图的限制

主物化视图和物化视图都基于 物化视图必须:

成为主键物化视图 驻留在兼容级别为 9.0.1 或更高版本的数据库中

注意:COMPATIBLE 初始化参数控制数据库的 兼容性级别。

不过,我会为您尝试一个解决方案。我会回来的。

更新:对不起,我没有成功。你的限制太多了:)

【讨论】:

“限制太多”?你的意思是?我有什么限制?【参考方案3】:

根据 Oracle 文档,您可能不走运:

http://download.oracle.com/docs/cd/B28359_01/server.111/b28313/basicmv.htm#i1006734

您可以在实体化视图上创建嵌套实体化视图,但所有父级和基础 物化视图必须包含连接或聚合。如果物化视图的定义查询不包含连接或聚合,则不能嵌套。 定义物化视图的所有底层对象(物化视图或表)都必须具有物化视图日志。所有基础对象都被视为表。此外,您可以将所有现有选项用于物化视图。

【讨论】:

以上是关于Oracle物化视图错误:包含代码的主要内容,如果未能解决你的问题,请参考以下文章

实体框架中的 Oracle 物化视图问题

oracle物化视图错误

Oracle - 子查询的物化视图

oracle物化视图不会自动更新是怎么回事

oracle 物化视图 job

物化视图基础概念mview跨库迁移表