Hej,
Mam następujący problem -
Istnieje sobie na bazie widok materialized view fast on commit, coś w stylu
create or replace materialized view mv_test
refresh fast on commit
as
select ..
union all
select
union all
etc..
Problem: baza musi obsługiwać distributed transactions, a więc nie możemy posiadać widoku 'refresh on commit'. Kod korzystający z widoku jest dość zawiły i generalnie moja idea jest taka, że chciałbym jakoś wymusić jego odświeżanie ręcznie przy każdym zapytaniu (zrobić ON DEMAND).
Jak do tej pory miałem pomysły opakowania odwołań do widoku w funkcję i wywoływania DBMS_MVIEW.refresh(), po czym zwracania wyników ale wydajność tego raczej bym powiedział że średnia już przez samo przetwarzanie zapytania i tworzenia zwracanego zestawu wierszy. Drugim pomysłem było stworzenie funkcji z samym odświeżeniem widoku np. funkcja_odswiez i zrobienie zapytania w stylu:
select funkcja_odswiez(), null, null, null ... from dual
union
select * from mv_widok
Niestety, kiedy próbuje stworzyć funkcję:
create or replace function refresh_fn
return number
as
v_ret number;
begin
DBMS_MVIEW.refresh('mv_test');
select 1 into v_ret from dual;
end refresh_fn;
I ją wywołać:
select refresh_fn(), null, null, null, null, null, null from dual;
Otrzymuję błąd
ORA-14552: cannot perform a DDL, commit or rollback inside a query or DML
ORA-06512: at "SYS.DBMS_SNAPSHOT", line 3014
ORA-06512: at "SYS.DBMS_SNAPSHOT", line 2994
ORA-06512: at "DEVCA.REFRESH_FN", line 7
14552. 00000 - "cannot perform a DDL, commit or rollback inside a query or DML "
*Cause: DDL operations like creation tables, views etc. and transaction
control statements such as commit/rollback cannot be performed
inside a query or a DML statement.
*Action: Ensure that the offending operation is not performed or
use autonomous transactions to perform the operation within
the query/DML operation.
Ostatecznością będzie wywołanie procedury DBMS_MVIEW.refresh('DKWTEST_MV'); przed każdym użyciem widoku ale wolałbym to jakoś ładnie zrobić w procedurze i np. dodać sprawdzanie czy w ogóle widok jest oznaczony jako STALE.