Как отловить ошибки при обновлении вложенных материализованных представлений - PullRequest
1 голос
/ 02 апреля 2019

Материализованный вид "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 пытается обновить вложенные MV и войти в таблицу.

Использование Oracle 11g.

1 Ответ

1 голос
/ 02 апреля 2019

Блок 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
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...