Oracle DB, Oracle APEX, Linux etc.

суббота, 2 октября 2010 г.

Nested Materialized Views: Must contain joins or aggregates. No exclusions...

Data Warehousing Guide говорит нам:

You can create a nested materialized view on materialized views, but all parent and base materialized views must contain joins or aggregates. If the defining queries for a materialized view do not contain joins or aggregates, it cannot be nested.

Как по мне, это условие насчёт обязательности агрегатов или соединения иногда только мешает. Например, у нас есть материализованное представление, необходимо на его основе сделать ещё одно, использующее детерминированные пользовательские функции для расчёта значений столбцов и быстро обновляющееся при фиксации изменений (REFRESH FAST ON COMMIT). Попробуйте этого добиться без агрегатов и соединений в запросе материализованного представления - у Вас ничего не выйдет, как бы Вы не ухищрялись с текстом запроса и журналом материализованного представления!

Решение простое: добавьте соединение с тем же самым материализованным представлением, используя rowid в качестве столбца-соединителя, выполните требования к материализованным представлениям с соединением для быстрого обновления - вуаля! Всё работает.

Тест-кейс:
create materialized view log on emp
  with rowid (empno, mgr, sal)
  including new values;
  
create materialized view mv$sub_sal
  refresh fast on commit
  as
select nvl(mgr, empno) mgr, sum(sal) sal, count(sal) sal_cnt, count(*) row_cnt
  from emp
 group by nvl(mgr, empno);
 
create function test_fu(p_mgr number, p_sal number)
  return number
  deterministic
as
begin
  return p_sal * case when p_sal > 5000 or p_mgr = 7788 then 1.2 else 1 end;
end;
/

alter table mv$sub_sal add constraint mv$sub_sal_pk primary key(mgr);

create materialized view log on mv$sub_sal
  with rowid;
  
create materialized view mv$calc_sub_sal
  refresh fast on commit
  as
select m1.mgr, test_fu(m1.mgr, m1.sal) calc_sal, m1.rowid m1_row_id, m2.rowid m2_row_id
  from mv$sub_sal m1, mv$sub_sal m2
 where m1.rowid = m2.rowid;

Удаление:
drop materialized view mv$calc_sub_sal;
drop materialized view log on mv$sub_sal;
drop function test_fu;
drop materialized view mv$sub_sal;
drop materialized view log on emp;

Комментариев нет:

Отправить комментарий