Replace a materialized view in Postgres
As of PostgreSQL 9.4: Different to the documentation of CREATE VIEW, the documentation of CREATE MATERIALIZED VIEW does NOT mention the REPLACE keyword. There seems to be no shortcut aside from dropping all dependent objects and rebuilding each one.
When you do so, I can only recommend two small things:
- Use DROP MATERIALIZED VIEW blabla CASCADE to get a list of all dependent objects
- Do the drop and recreation of all dependent object in one transaction.
For my situation, I prefer to limit the drops by using a view layer:
- Create a copy of the materialized view suffixed with "_new" and also use "WITH NO DATA" for performance, make sure any indexes are also created with suffix and any other dependant objects discovered via DROP...CASCADE
- Create a view upon the new materialized view to provide the layer of abstraction so I only need to change it in one place
- ALTER the existing dependencies to instead refer to the new view (refreshing the data if needed beforehand)
- Drop the original materialized view and indices which should now not have any dependants
- ALTER THE materialized view and indices to drop the suffix to restore the original names
eg.
create table test (myfield int);
insert into test values (1);
create materialized view mv_test as select myfield from test;
create view v_test as select myfield from mv_test;
select * from v_test;
create materialized view mv_test_new as select myfield, myfield+1 as myfield2 from test;
alter view v_test rename to v_test_old;
alter materialized view mv_test rename to mv_test_old;
create view v_test as select myfield,myfield2 from mv_test_new;
select * from v_test;
alter materialized view mv_test_new rename to mv_test;
drop view v_test_old; -- when ready
drop materialized view mv_test_old; -- when ready