How to refresh materialized view using trigger?

manurajhada picture manurajhada · Oct 25, 2012 · Viewed 16.1k times · Source
create or replace TRIGGER REFRESH_REST_VIEW
 AFTER
  INSERT OR UPDATE
 ON tbl_contract
BEGIN
    execute DBMS_MVIEW.REFRESH('REST_VIEW');
END REFRESH_REST_VIEW;
commit;

This is my sql trigger i am using to refresh Materialized View. But it says..

Warning: execution completed with warning
TRIGGER REFRESH_REST_VIEW Compiled.

P.S. : The trigger will be executed when the data of table (used by Materialized View) takes any DML operation.

I have googled enough, many post says it is possible but I am not getting how to do it. I tried with regular trigger syntax and it doesn't works.

Updated:

Now i am trying to the same with Procedure and Trigger..

create or replace
PROCEDURE Rfresh_mate_views AS
  BEGIN
   DBMS_MVIEW.REFRESH('REST_VIEW');
  END Rfresh_mate_views;


create or replace trigger refresh_company_mview
after insert or update ON BCD.BCD_COMPANY
begin
RFRESH_MATE_VIEWS(); 
end refresh_company_mview;

All has been compiled successfully but while updating in the table it says:

ORA-04092: cannot COMMIT in a trigger
ORA-06512: at "SYS.DBMS_SNAPSHOT", line 2449
ORA-06512: at "SYS.DBMS_SNAPSHOT", line 2429
ORA-06512: at "BCD.RFRESH_MATE_VIEWS", line 3
ORA-06512: at "BCD.REFRESH_COMPANY_MVIEW", line 2
ORA-04088: error during execution of trigger 'BCD.REFRESH_COMPANY_MVIEW'

Answer

Justin Cave picture Justin Cave · Oct 25, 2012

It doesn't make sense to refresh a materialized view in a trigger.

You can resolve the syntax error by removing the word EXECUTE

create or replace TRIGGER REFRESH_REST_VIEW
 AFTER
  INSERT OR UPDATE
 ON tbl_contract
BEGIN
    DBMS_MVIEW.REFRESH('REST_VIEW');
END REFRESH_REST_VIEW;

That will cause the trigger to compile. However, when you try to execute an INSERT or an UPDATE against tbl_contract, you'll now get a runtime error that you are not allowed to commit in a trigger because doing a refresh of a materialized view does an implicit commit and you cannot commit inside a trigger.

SQL> create table foo( col1 number );

Table created.

SQL> create materialized view mv_foo
  2  as
  3  select *
  4    from foo;

Materialized view created.

SQL> create trigger trg_foo
  2    after insert or update on foo
  3  begin
  4    dbms_mview.refresh( 'MV_FOO' );
  5  end;
  6  /

Trigger created.

SQL> insert into foo values( 1 );
insert into foo values( 1 )
            *
ERROR at line 1:
ORA-04092: cannot COMMIT in a trigger
ORA-06512: at "SYS.DBMS_SNAPSHOT", line 2760
ORA-06512: at "SYS.DBMS_SNAPSHOT", line 2740
ORA-06512: at "SCOTT.TRG_FOO", line 2
ORA-04088: error during execution of trigger 'SCOTT.TRG_FOO'

You could potentially try to resolve that by blowing away your transactional integrity and doing the refresh in an autonomous transaction. That will eliminate the ORA-04092 error but then the materialized view won't have the uncommitted data that was inserted or updated as part of the transaction that fired the trigger in the first place which defeats the whole purpose of refreshing the materialized view.

The proper approach is not to use a trigger in the first place. The proper approach is to define the materialized view to refresh itself on commit-- REFRESH FAST ON COMMIT. Since you are getting an error that you cannot set the ON COMMIT attribute on the materialized view, you'll want to look at the restrictions on fast refresh that are listed in the Data Warehousing Guide and make sure your materialized view should be fast-refreshable. Then, you can use the dbms_mview.explain_mview procedure to tell you why the materialized view isn't eligible to be refreshed incrementally on commit.