When I run the following code on 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
);
I get this error upon trying to create the materialized view 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 obje开发者_JAVA百科cts 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.
I don't understand how any of the objects in the "FROM clause" depend on each other.
How do I get this to work? Currently the only work around I can think of is to replace test3
with a ordinary table and manually delete and refresh the data. This approach works, but seems like a bit of a hack.
Alternatively (and perhaps preferably) I'd just like to see an example where can have two tables, and join them into a materialized view, where one of the base tables is bulk updated (and does not need to be reflected in the materialized view) but the others updates should be reflected in the materialized view (i.e. it's kind of "half" fast refresh on commit
, and half complete refresh on demand
). I tried using refresh force
, but when using EXECUTE DBMS_MVIEW.EXPLAIN_MVIEW()
I found no evidence of fash refresh on commit being available. I'd also like to do this with union all
s as well.
You can make the test4 materialized view refresh fast like this:
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.
Your case doesn't work because for a nested MV to work, an underlying MV cannot be a basic MV. This sounds strange at first, but you'd need a trick like you did with test3 to make it work. Also, for a join MV to work, the materialized view logs of the underlying table need to be created WITH ROWID.
You might want to look at a series of blog posts I wrote about fast refreshable materialized view errors. They describe almost all restrictions:
Basic MV's
Join MV's
Aggregate MV's
Union all MV's
Nested MV's
MV_CAPABILITIES_TABLE
Summary
Regards,
Rob.
Added: 29-09-2011
Here is an example with a nested MV using the union all trick on test2 as well:
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.
Hope this helps!
Quoting from Oracle
Restrictions for Using Multitier Materialized Views
Both master materialized views and materialized views based on materialized views must:
- Be primary key materialized views
- Reside in a database that is at 9.0.1 or higher compatibility level
Note: The COMPATIBLE initialization parameter controls a database's compatibility level.
However, I'll try a solution for you. I'll be back.
Update: Sorry I didn't succeded. You have too many restrictions :)
You may be out of luck, per the Oracle documentation:
http://download.oracle.com/docs/cd/B28359_01/server.111/b28313/basicmv.htm#i1006734
You can create a nested materialized view on materialized views, but all parent and base materialized views must contain joins or aggregates. If the defining queries for a materialized view do not contain joins or aggregates, it cannot be nested. All the underlying objects (materialized views or tables) on which the materialized view is defined must have a materialized view log. All the underlying objects are treated as if they were tables. In addition, you can use all the existing options for materialized views.
精彩评论