#oracle #materialized-views
#Oracle #материализованные представления
Вопрос:
Материализованный вид «MV_AMP»:
CREATE MATERIALIZED VIEW MV_AMP
NOLOGGING
BUILD IMMEDIATE
REFRESH FORCE
ON DEMAND
AS
Select a, b, c from amp;
Материализованный вид «MV_BOT», зависящий от «MV_AMP»:
CREATE MATERIALIZED VIEW MV_BOT
NOLOGGING
BUILD IMMEDIATE
REFRESH FORCE
ON DEMAND
AS
SELECT bot.x, bot.y, mv_amp
FROM bot, mv_amp
WHERE bot.a = mv_amp.a;
И создайте уникальный индекс в mv_bot:
CREATE UNIQUE INDEX mv_bot_idx001 ON mv_bot(x, a);
После успешного создания представлений и индекса предположим, что я добавляю повторяющееся значение, которое вызывает ошибку типа (dup_val_on_index) при обновлении mv_bot из-за уникального индекса.
Итак, я выполняю обновление в MV_AMP (главном представлении), используя nested = TRUE, и Oracle не выдал ошибку:
BEGIN
dbms_mview.refresh_dependent(number_of_failures => n_failures,
list => 'MV_AMP',
atomic_refresh => TRUE,
nested => TRUE);
EXCEPTION
WHEN
OTHERS THEN
-- it never reach this code
dbms_output.put_line('Errors: '||SQLERRM);
END;
n_failures возвращает: 0 и он никогда не достигает dbms_output внутри исключения.
Мне нужно перехватить ошибку, когда oracle пытается обновить вложенные MVS и войти в таблицу.
Использование Oracle 11g.
Ответ №1:
EXCEPTION
Блок достигается только в том случае, если в материализованном представлении есть дублированная строка MV_BOT
, что не так.
Вы можете спросить, почему; наиболее вероятный ответ заключается в том, что вам также MV_AMP
необходимо обновить материализованное представление, чтобы получить дубликат при объединении ……….. MV_BOT
При чтении документации dbms_mview.refresh_dependent
вы понимаете, что вы должны начать с таблицы AMP
, чтобы обновить оба MV (начиная с MV_AMP
, обновляется только зависимый MV MV_BOT
)
Тестовый пример
create table amp (
a number,
b number,
c number);
create table bot (
a number,
x number,
y number);
CREATE MATERIALIZED VIEW MV_AMP
NOLOGGING
BUILD IMMEDIATE
REFRESH FORCE
ON DEMAND
AS
Select a, b, c from amp;
CREATE MATERIALIZED VIEW MV_BOT
NOLOGGING
BUILD IMMEDIATE
REFRESH FORCE
ON DEMAND
AS
SELECT bot.x, bot.y, mv_amp.a
FROM bot, mv_amp
WHERE bot.a = mv_amp.a;
CREATE UNIQUE INDEX mv_bot_idx001 ON mv_bot(x, a);
insert into amp(a,b,c) values(1,1,1);
insert into bot(a,x,y) values(1,1,1);
insert into bot(a,x,y) values(1,1,3);
commit;
DECLARE
n_failures NUMBER;
BEGIN
dbms_mview.refresh_dependent(number_of_failures => n_failures,
list => 'AMP',
atomic_refresh => TRUE,
nested => TRUE);
dbms_output.put_line('Failures: '||n_failures);
EXCEPTION
WHEN
OTHERS THEN
dbms_output.put_line('Errors: '||SQLERRM);
END;
/
--> Errors: ORA-12008: error in materialized view refresh path
--> ORA-00001: unique constraint (xxxxx.MV_BOT_IDX001) violated
Комментарии:
1. Возможно, мой пример не совсем объясняет проблему. Пожалуйста, игнорируйте значения, представленные в таблицах примеров, рассмотрите только эти 2 MVS, MV_BOT зависит от MV_AMP. В реальном сценарии в MV_BOT возникает дублированная строка, потому что у нее есть соединения с другими таблицами, которые вызывают это. Если я не начну обновление с «MV_AMP», как я узнал основную таблицу этого представления? В реальном сценарии у него есть выбор из 3 или 4 разных таблиц.
2. @Joel моя точка зрения другими словами — вы обновляете PL / SQL, который только обновляет
MV_BOT
и сохраняетMV_APP
неизменным. Вы должны выбрать некоторый источникMV_APP
(здесьAPP
) в качестве отправной точки для обновления обоих MVS.3. Попытался запустить dbms_mview.refresh_dependent с главной таблицей из MV_AMP, но, к сожалению, получил тот же результат. MV_BOT не был обновлен из-за повторяющихся значений в индексе, и процесс обновления не вызвал никакой ошибки.
4. @Joel Я добавил воспроизводимый пример, вызывающий
unique constraint
исключение. Вы можете попытаться обобщить свой пробег. Обратите также внимание, что в вашемMV_BOT
DDL есть синтаксическая ошибка , которую я исправил, используяmv_amp.a
вместоmv_amp
— надеюсь, это только опечатка.