Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Oracle materialized view error: code included

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 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.

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 alls as well.

like image 280
Clinton Avatar asked Sep 20 '11 02:09

Clinton


2 Answers

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!

like image 119
Rob van Wijk Avatar answered Nov 01 '22 08:11

Rob van Wijk


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 :)

like image 29
Florin stands with Ukraine Avatar answered Nov 01 '22 08:11

Florin stands with Ukraine