We are using USER_DEPENDENCIES in order to generate up-to-date documentation of our application ETL layer in DOT-language style (see graphviz) which is being added as dynamic dependency graphs into our internal WIKI. While checking the resulting graph we identified an issue with the reported dependencies for materialized views (MV). Whenever a MV is selecting from another view, the dependencies of the view are shown as dependencies of the MV
as well (observed in 12.1.0.2.0).
NOTE: The issue reported in
https://asktom.oracle.com/pls/apex/asktom.search?tag=mview-dependencies refers to missing dependencies.
Test setup (see
https://livesql.oracle.com/apex/livesql/s/i0pvsa3a1lyi6wu7ufykw06ok ):
create table t1 (c1 int);
create view v1 as select * from t1;
create materialized view v2 as select * from v1;
Querying the dependencies from USER_DEPENDENCIES
select name, type, referenced_name, referenced_type from user_dependencies where name in ('T1','V1','V2') order by name desc, referenced_name desc;
Result:
NAME,TYPE,REFERENCED_NAME,REFERENCED_TYPE
V2, MATERIALIZED VIEW, V2, TABLE
V2, MATERIALIZED VIEW, V1, VIEW
V2, MATERIALIZED VIEW, T1, TABLE -- this dependencies seems to be wrong for me
V1, VIEW, T1, TABLE
When using a view instead of a materialized view, the dependencies are as expected:
create view v2b as select * from v1;
select name, type, referenced_name, referenced_type from user_dependencies where name in ('T1','V1','V2B') order by name desc, referenced_name desc;
Result:
NAME,TYPE,REFERENCED_NAME,REFERENCED_TYPE
V2B, VIEW, V1, VIEW
V1, VIEW, T1, TABLE
* Isn't the first result wrong?
* Is there any way to hinder showing dependencies of underlying views as dependencies of the MV?
This is expected behaviour.
The database needs to know when you change the data a materialized view uses. So it has a dependency right down to the base tables uses. Even if you access these via a view.
This ensures it can track the freshness of an MV correctly.
Personally I'd want to keep this documented, so you know when you need to refresh an MV. Or which transactions will trigger a refresh if you have REFRESH FAST ON COMMIT.
If you must remove the tables, you could do something like:
- Find all the tables referenced in views
- Where the views are used in materialized views
- Then minus these from the MV dependencies
e.g.:
select name, type, referenced_name, referenced_type
from user_dependencies ud
where name in ('V2')
minus
select 'V2', 'MATERIALIZED VIEW', referenced_name, referenced_type
from user_dependencies ud
where referenced_type = 'TABLE'
and type = 'VIEW'
and exists (
select * from user_dependencies ud2
where ud2.referenced_name = ud.name
and ud2.type = 'MATERIALIZED VIEW'
);
NAME TYPE REFERENCED_NAME REFERENCED_TYPE
V2 MATERIALIZED VIEW V1 VIEW
V2 MATERIALIZED VIEW V2 TABLE But this quickly gets a pain - what if you have MV -> VIEW -> VIEW -> VIEW -> TABLE?