Question

I need to change quite a huge amount of materialized views to usual views on Oracle 11g. My first approach:

1.) Get the DDLs

select dbms_metadata.get_ddl(replace(object_type, ' ', '_'), object_name, owner)
from all_objects
where owner = 'MY_SCHEMA'
and object_type = 'MATERIALIZED VIEW'
and object_name in (
'MAT_VIEW1'
,'MAT_VIEW2'
,'MAT_VIEW3'
,'MAT_VIEW4'
-- ..
,'MAT_VIEW100'
); 

Each row contains the DDL for the corresponding MVIEW, f.e.:

  CREATE MATERIALIZED VIEW "MY_SCHEMA"."MVIEW1" ("ROW1", "ROW2", "ROW3")
  ORGANIZATION HEAP PCTFREE 0 PCTUSED 40 INITRANS 1 MAXTRANS 255 
  NOCOMPRESS NOLOGGING
  STORAGE(INITIAL 163840 NEXT 1048576 MINEXTENTS 1 MAXEXTENTS 2147483645
  PCTINCREASE 0 FREELISTS 1 FREELIST GROUPS 1
  BUFFER_POOL DEFAULT FLASH_CACHE DEFAULT CELL_FLASH_CACHE DEFAULT)
  TABLESPACE "MY_TABSPACE" 
  BUILD IMMEDIATE
  USING INDEX PCTFREE 10 INITRANS 2 MAXTRANS 255 
  STORAGE(INITIAL 65536 NEXT 1048576 MINEXTENTS 1 MAXEXTENTS 2147483645
  PCTINCREASE 0 FREELISTS 1 FREELIST GROUPS 1
  BUFFER_POOL DEFAULT FLASH_CACHE DEFAULT CELL_FLASH_CACHE DEFAULT)
  TABLESPACE "MY_TABLESPACE" 
  REFRESH FORCE ON DEMAND
  WITH PRIMARY KEY USING DEFAULT LOCAL ROLLBACK SEGMENT
  USING ENFORCED CONSTRAINTS DISABLE QUERY REWRITE
  AS SELECT ROWA AS ROW1,
  ROWB AS ROW2,
  ROWC AS ROW3
  FROM MY_SCHEMA.TABLE1

2.) Get rid of the additional technical configuration by using a regular expression. For convenience I use RegexBuddy and copy paste the text. Oracle doesn't support Look Forward/Backward features as fas as I noticed:

(?=ORGANIZATION\sHEAP).+?(QUERY\sREWRITE)

Result:

  CREATE MATERIALIZED VIEW "MY_SCHEMA"."MVIEW1" ("ROW1", "ROW2", "ROW3")
  AS SELECT ROWA AS ROW1,
  ROWB AS ROW2,
  ROWC AS ROW3
  FROM MY_SCHEMA.TABLE1

At last I removed "MATERIALIZED" from each the DDL, now I have the valid DDLs for the views.

Meanwhile I got a spontanious idea and just tried

create view usual_view1 as
select * from mat_view1;

Hm, that worked as well, with quite less effort.

So my question: is there any difference in the end when creating views from the definition of a materialized view in comparision to the usual way of creating it by DDL?

Was it helpful?

Solution

When you create the view the second way, with:

create view usual_view1 as
select * from mat_view1;

... your view is showing you the data held by the materialised view, not the underlying tables. As that is refresh force on demand your 'normal' view will only show the stale data held by the materialised view, not the current state of the data in the underlying tables.

More importantly, if the materialised view is dropped - which seems likely as you seem to be replacing them - then your 'normal' view will become invalid.

create materialized view my_mview
refresh force on demand
as select * from dual;

materialized view MY_MVIEW created.

create view my_view as select * from my_mview;

view MY_VIEW created.

select * from my_view;

DUMMY
-----
X     

drop materialized view my_mview;

materialized view MY_MVIEW dropped.

select * from my_view;

SQL Error: ORA-04063: view "STACKOVERFLOW.MY_VIEW" has errors

select text from user_errors where name = 'MY_VIEW';

ORA-00942: table or view does not exist

Clearly dual still exists, it's my_mview that it can't find any more. The view has no knowledge of the underlying tables of the materialised view - it has not inherited the query used by that, it is only showing what it contains. They are very different things.


You could cut out some of the noise from the DDL approach with dbms_metadata.set_transform_param() calls, but you can't get it completely clean as far as I'm aware. You could though just get the underlying query:

select query
from all_mviews where owner = 'STACKOVERFLOW'
and mview_name = 'MY_MVIEW';

QUERY                                                      
------------------------------------------------------------
select * from dual                                           

You can manipulate that to put the create view ... as at the start; although as query is a long column I think you'll have to do it in a PL/SQL block, something like:

begin
  for r in (
    select mview_name, query
    from all_mviews
    where owner = 'STACKOVERFLOW'
    and mview_name = 'MY_MVIEW'
  ) loop
    dbms_output.put_line('create or replace view '
       || replace(r.mview_name, 'MVIEW', 'VIEW')
       || ' as ' || r.query ||';');
  end loop;
end;
/

anonymous block completed
create or replace view MY_VIEW as select * from dual;
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top