Skip to Main Content
  • Questions
  • Materialized View Fast refresh containing UNION

Breadcrumb

Question and Answer

Tom Kyte

Thanks for the question, Lucy.

Asked: November 17, 2002 - 7:56 pm UTC

Last updated: October 10, 2013 - 1:40 pm UTC

Version: 9.2.0

Viewed 10K+ times! This question is

You Asked

We would like to be able to use fast refresh on a materialised view which contains a union.
This has worked when the union uses the same table. However it does not seem to work with a different table name even though the primary key, and columns selected are identical. We are using Oracle9i Enterprise Edition Release 9.2.0.1.0.

The example that worked:

Table name QH_PAT.
Name Null? Type
------------------------------- -------- ----
FCLTY_ID NOT NULL VARCHAR2(6)
PAT_ID NOT NULL VARCHAR2(8)
SEX NOT NULL VARCHAR2(6)
BIRTH_DATE NOT NULL DATE
BIRTH_DATE_EST_CODE VARCHAR2(6)
VALID_FROM NOT NULL DATE
VALID_TO NOT NULL DATE
FCLTY_UNIQUE_ID NOT NULL VARCHAR2(12)

Primary Key:
alter table qh_pat
add constraint qh_pat_pk
primary key
(
fclty_id,
fclty_unique_id
);


Snapshot log script:
create snapshot log on QH_PAT
with primary key

Materialized View script:
create snapshot qh_pat_mv as
select fclty_id,
fclty_unique_id,
pat_id,
sex,
birth_date_est_code
from qh_pat
where sex = ‘1’
union
select fclty_id,
fclty_unique_id,
pat_id,
sex,
birth_date_est_code
from qh_ pat
where sex = ‘2’
/

The example that creates a complex materialized view that will not allow fast refresh:

Table Name: QH_WORK_PAT
FCLTY_ID NOT NULL VARCHAR2(6)
PAT_ID NOT NULL VARCHAR2(8)
SEX VARCHAR2(6)
BIRTH_DATE VARCHAR2(8)
BIRTH_DATE_EST_CODE VARCHAR2(6)
VALID_FROM NOT NULL VARCHAR2(12)
VALID_TO VARCHAR2(12)
FCLTY_UNIQUE_ID NOT NULL VARCHAR2(12)

Primary Key:
alter table qh_work_pat
add constraint qh_work_pat_pk
primary key
(
fclty_id,
fclty_unique_id
);

Snapshot log script:
create snapshot log on QH_WORK_PAT
with primary key


Materialized View Script:
create snapshot qh_pat_mv as
select fclty_id,
fclty_unique_id,
pat_id,
sex,
birth_date_est_code
from qh_pat
union
select fclty_id,
fclty_unique_id,
pat_id,
sex,
birth_date_est_code
from qh_work_pat

In the first example using QH_PAT only, I can include ‘refresh fast with primary key’ in the script. This also is ok if QH_WORK_PAT is used for both queries.
In the second example using QH_PAT and QH_WORK_PAT. If I put ‘refresh fast with primary key’ in the create script I get the following error.
Creating snapshot QH_PAT_MV
qh_work_pat
*
ERROR at line 18:
ORA-12015: cannot create a fast refresh materialized view from a complex query

According to the 9i documentation a union does not make a materialized view complex unless one of the defining queries is complex. I can not see any mention of having different table names as a cause of ’complex’.

Have you any ideas.

and Tom said...

Can you use a UNION ALL instead of a UNION?

UNION ALLS are supported.

A union B is like:

distinct (sort ( A + B ))

A union all B is like:

A + B


if you do not need the sort/distinct, UNION ALL is the way to go. As you can imagine, trying to do a fast refresh from a UNION view of two tables would be very very hard. Suppose you just have two tables with one column each and one row each. Each has a row with X=1. So,

a union b = { 1 }

just one tuple. Now, you delete from B. How do you apply that ? That delete should have no net effect on the materialized view -- but you don't know that unless you reprocess the entire A union B.

with a UNION ALL -- it would be possible but you'll need to add some maintenance columns:

ops$tkyte@ORA920.US.ORACLE.COM> create table t1 ( x int primary key, y int );

Table created.

ops$tkyte@ORA920.US.ORACLE.COM> create table t2 ( x int primary key, y int );

Table created.

ops$tkyte@ORA920.US.ORACLE.COM>
ops$tkyte@ORA920.US.ORACLE.COM> create snapshot log on t1 with primary key, rowid;

Materialized view log created.

ops$tkyte@ORA920.US.ORACLE.COM> create snapshot log on t2 with primary key, rowid;

Materialized view log created.

ops$tkyte@ORA920.US.ORACLE.COM>
ops$tkyte@ORA920.US.ORACLE.COM> create materialized view mv2
2 refresh fast
3 as
4 select x, y from t1
5 union
6 select x, y from t2
7 /
select x, y from t2
*
ERROR at line 6:
ORA-12015: cannot create a fast refresh materialized view from a complex query


ops$tkyte@ORA920.US.ORACLE.COM>
ops$tkyte@ORA920.US.ORACLE.COM> create materialized view mv2
2 refresh fast
3 as
4 select x, y, 1 umarker , rowid rid from t1
5 union ALL
6 select x, y, 2 umarker , rowid rid from t2
7 /

Materialized view created.


See
</code> http://docs.oracle.com/cd/B10501_01/server.920/a96520/mv.htm#574889 <code>

for the details on this new 9iR2 feature -- you cannot do UNION ALL mv's before that release




Rating

  (11 ratings)

Is this answer out of date? If it is, please let us know via a Comment

Comments

A reader, November 18, 2002 - 6:54 pm UTC


Is there a way to do this on remote base tables?

Raj, February 25, 2005 - 2:19 pm UTC

Tom,

According to the 9iR2 documentation, I understand that there is a restriction that remote tables are not supported for materialized views with UNION ALL.

Is there any workaround though?

Thanks.

Tom Kyte
February 25, 2005 - 6:35 pm UTC

link to documentation in context please (otn.oracle.com -> documentation)

and more precisness -- what kind of MV...

Raj, February 28, 2005 - 11:56 am UTC

Sorry for incomplete information.
I meant fast refreshable materialized views with UNION ALL and having remote tables in queries.


Tom Kyte
February 28, 2005 - 12:08 pm UTC

</code> http://docs.oracle.com/docs/cd/B10501_01/server.920/a96567/repmview.htm#25391 <code>

it would be considered a complex materialized view.


You would create two MV's (each can be fast refreshed) and a LOCAL view that union all's them together perhaps.

Very Useful

venkatesh, June 17, 2005 - 2:18 am UTC

yr solution is very useful, i have faced the same problem and search for the ans, at the time i got this. Thank you very much

Interesting

Avishay, December 19, 2005 - 8:17 am UTC

CREATE MATERIALIZED VIEW MV_LOV_LOCAL
REFRESH FAST
AS
SELECT * from dwsrc.LOV_LOCAL_CHANGE
UNION ALL
SELECT * FROM dwsrc.lov_local_termination

ORA-12015: cannot create a fast refresh materialized view from a complex query

Both tables are built the same with same definition of primary_key and same number of columns

Any suggestions will be appreciated


Tom Kyte
December 19, 2005 - 8:33 am UTC

</code> http://docs.oracle.com/docs/cd/B19306_01/server.102/b14223/basicmv.htm#sthref508 <code>

you have not satisfied all of the necessary requirements.

Creating a MV from multiple instances

Florin, January 18, 2006 - 10:44 am UTC

Hi Tom,

I'm trying to create a snapshot based on 2 tables from 2 different instances. Example:

First instance:

sqlplus admin/admin@nmx

SQL> create table t1 (a1 number);

Table created.

SQL> grant all on t1 to public;

Grant succeeded.

SQL> insert into t1 values (1);

1 row created.

SQL> insert into t1 values (2);

1 row created.

SQL> commit;

SQL> alter table t1 add constraint t1_pk primary key (a1) using index;

Table altered.

SQL>  create snapshot log on t1;

Materialized view log created.

Second instance:

SQL> conn admin/admin@BML1
Connected.
SQL> create table t2 (b2 number);

Table created.

SQL> insert into t2 values (3);

1 row created.

SQL> insert into t2 values (4);

1 row created.

SQL> commit;

Commit complete.

SQL> alter table t2 add constraint t2_pk primary key (b2) using index;

Table altered.

SQL> create snapshot log on t2;

Materialized view log created.

SQL> grant all on t2 to public;

Grant succeeded.

Third instance:

SQL> conn admin/admin@BML8I
Connected.
SQL> create database link nmx connect to admin identified by admin using 'NMX';

Database link created.

SQL> create database link BML1 connect to admin identified by admin using 'BML1';

Database link created.

SQL> create snapshot t_snap using index refresh fast start with sysdate with rowid as select * from admin.t1@nmx,admin.t2@BML1;
create snapshot t_snap using index refresh fast start with sysdate with rowid as select * from admin.t1@nmx,admin.t2@BML1
                                                                                        *
ERROR at line 1:
ORA-12015: cannot create a fast refresh snapshot from a complex query


I've tried also your suggestion:

SQL> create snapshot t_snap refresh fast as
  2  select a1 , 1 umarker , rowid rid from admin.t1@ibs9dm
  3  union all
  4  select b2 , 2 umarker , rowid rid from admin.t2@nmx9;
select a1 , 1 umarker , rowid rid from admin.t1@ibs9dm
       *
ERROR at line 2:
ORA-12015: cannot create a fast refresh materialized view from a complex query


Would you please advise?
Many thanks in advance,
Florin

 

Tom Kyte
January 19, 2006 - 7:49 am UTC

you have cartesian joins in the first case. And you cannot fast refresh a query from TWO databases.

you cannot do union all views over two database links in the other.


create snapshot is "deprecated", use create materialized view.

fast refresh mv as mv1 union all mv2

Tomislav Kokoska, January 17, 2013 - 2:53 pm UTC

create table t1 (id number, name varchar2(10), constraint t1_pk primary key (id))

create table t2 (id number, name varchar2(10), constraint t2_pk primary key (id))


drop materialized view log on t1


drop materialized view log on t2

create materialized view log on t1 with primary key, rowid (name) including new values

create materialized view log on t2 with primary key, rowid (name) including new values


select * from mlog$_t1


drop materialized view mv1

create materialized view mv1
build immediate
refresh fast on commit
as
select t1.*, rowid ridt1 from t1;



drop materialized view mv2



create materialized view mv2
build immediate
refresh fast on commit
as
select t2.*, rowid ridt2 from t2;


drop materialized view log on mv1

drop materialized view log on mv2

create materialized view log on mv1 with primary key, rowid (name, ridt1) including new values

create materialized view log on mv2 with primary key, rowid (name, ridt2) including new values



create or replace view v as
(
select '1' markup, rowid rid, id, name, ridt1 from mv1
union all
select '2' markup, rowid ris , id, name, ridt2 from mv2
)


create materialized view mv
build immediate
refresh fast on commit
as
select * from v;


ORA-12053: this is not a valid nested materialized view

What's wrong??
Tom Kyte
January 18, 2013 - 10:09 am UTC

ops$tkyte%ORA11GR2> create materialized view mv
  2  build immediate
  3  refresh fast on commit
  4  as
  5  select * from v;

Materialized view created.

ops$tkyte%ORA11GR2> select * from v$version;

BANNER
--------------------------------------------------------------------------------
Oracle Database 11g Enterprise Edition Release 11.2.0.3.0 - Production
PL/SQL Release 11.2.0.3.0 - Production
CORE    11.2.0.3.0      Production
TNS for Linux: Version 11.2.0.3.0 - Production
NLSRTL Version 11.2.0.3.0 - Production

ops$tkyte%ORA11GR2> 



I cannot reproduce.

About MV fast refresh errors

Rob van Wijk, January 19, 2013 - 4:25 am UTC

Tomislav,

I have a blogpost that you can use when you encounter a fast refreshable MV error: http://rwijk.blogspot.nl/2009/09/fast-refreshable-materialized-view_13.html

Your ORA-12053 is explained in this blogpost: http://rwijk.blogspot.nl/2009/08/fast-refreshable-materialized-view.html The base MV's (mv1 and mv2) need not be simple MV's if you want to nest them.

Hope this helps.

Regards,
Rob.

fast refresh mv as mv1 union all mv2

Tomislav, January 22, 2013 - 5:08 pm UTC

Actualy i have a table_arhive union all mv1.if i'm using table union all table everything is ok. You posted to use complex mv instead simple one. You're wright, making mv with count(*) and group by all columns mv become complex and mv as mv1_count union all mv2_count was created. Thanks a lot!

query with IN clause for M-view

A reader, October 10, 2013 - 8:16 am UTC

hi tom i have the below 3 tables and i am creating a view on these 3 tables:

table 1:

create table sprt_ec_device_attr
(
GUID number primary key,
ATTR_DEF_GUID number,
OBJECT_ID number,
ATTR_INDEX number,
ATTR_VALUE number,
CREATED date,
CREATED_BY number,
MODIFIED date,
MODIFIED_BY number
);

table2:

create table dwh_attribute
(
GUID number primary key
);

tbale3:
create table dwh_device
(
GUID number primary key
);

view on 3 detail tables:

1. CREATE OR REPLACE VIEW DWH_DEVICE_ATTRIBUTE AS
2. SELECT
3. GUID
4. , ATTR_DEF_GUID
5. , OBJECT_ID AS DEVICE_ID
6. , ATTR_INDEX
7. , ATTR_VALUE
8. , CREATED
9. , CREATED_BY
10. , MODIFIED
11. , MODIFIED_BY
12. FROM sprt_ec_device_attr
13. WHERE
14. ATTR_DEF_GUID IN
(SELECT guid FROM dwh_attribute)
15. AND
16. OBJECT_ID IN
(SELECT guid FROM dwh_device);

now i am going to create M-view on the above view. while creating M-view it throws erro saying that, the select query used in view creation is making query a complex query i.e. line number 14 and 16 as below .

now when i replace the line 14 and 16 by below,the M-view gets created

14. ATTR_DEF_GUID IN
(1,2)
15. AND
16. OBJECT_ID IN
(3,5,6);


plesae explain this behaviour

Tom Kyte
October 10, 2013 - 1:40 pm UTC

you really have to provide an example that actually reproduces the issue so we can actually - well you know - see what you did.

for you see, I just read this and say "hmmm, missing the create materialized view statement, let me add it:"

ops$tkyte%ORA11GR2> create materialized view mv
  2  as
  3   SELECT
  4   GUID
  5   , ATTR_DEF_GUID
  6   , OBJECT_ID  AS DEVICE_ID
  7   , ATTR_INDEX
  8   , ATTR_VALUE
  9   , CREATED
 10   , CREATED_BY
 11    , MODIFIED
 12    , MODIFIED_BY
 13    FROM sprt_ec_device_attr
 14    WHERE
 15    ATTR_DEF_GUID IN
 16    (SELECT guid FROM dwh_attribute)
 17    AND
 18    OBJECT_ID IN
 19    (SELECT guid FROM dwh_device);

Materialized view created.



apparently you are doing it differently. We might actually have to see that - you know, to understand what exactly it is you are doing.


sort of like the examples I post for all of you guys that go from start to finish - that include everything, but that are as teeny tiny as humanly possible.

IN clause replaced with EXISTS clause to avoid complex query

A reader, November 14, 2013 - 10:17 am UTC

hi tom,
the create script for materialized view as as below:

create materialized view M_view_DWH as select * from DWH_DEVICE_ATTRIBUTE;

previously i was using IN clause in my query. one of my colleague told me to use EXISTS clause.
i used it and the error of "complex query" was gone.

i further checked for it and find in one of your post that
1)the IN clause is internally rewritten by oracle using the DISTINCT , which makes query complex.

2.) whereas EXISTS is internally rewritten using FOR, which will keep the query simple