Подтвердить что ты не робот

Как поймать уникальную ошибку ограничения в блоке PL/SQL?

Скажем, у меня есть блок PL/SQL Oracle, который вставляет запись в таблицу и должен восстанавливаться с уникальной ошибки ограничения, например:

begin
    insert into some_table ('some', 'values');
exception
    when ...
        update some_table set value = 'values' where key = 'some';
end;

Можно ли заменить многоточие на что-то, чтобы поймать уникальную ошибку ограничения?

4b9b3361

Ответ 1

EXCEPTION
      WHEN DUP_VAL_ON_INDEX
      THEN
         UPDATE

Ответ 2

Я уверен, что у вас есть свои причины, но на всякий случай... вы также должны использовать вместо этого запрос "merge":

begin
    merge into some_table st
    using (select 'some' name, 'values' value from dual) v
    on (st.name=v.name)
    when matched then update set st.value=v.value
    when not matched then insert (name, value) values (v.name, v.value);
end;

(изменено выше, чтобы быть в блоке begin/end, очевидно, вы также можете запускать его независимо от этой процедуры).

Ответ 3

Я подозреваю, что условие, которое вы ищете, DUP_VAL_ON_INDEX

EXCEPTION
    WHEN DUP_VAL_ON_INDEX THEN
        DBMS_OUTPUT.PUT_LINE('OH DEAR. I THINK IT IS TIME TO PANIC!')

Ответ 4

В качестве альтернативы явному отлову и обработке исключения вы можете указать Oracle перехватывать и автоматически игнорировать исключение, включив /*+ hint */ в оператор вставки. Это немного быстрее, чем явно перехватывать исключение и затем формулировать, как оно должно обрабатываться. Это также проще в настройке. Недостатком является то, что вы не получаете никаких отзывов от Oracle о том, что возникло исключение.

Вот пример, в котором мы будем выбирать из другой таблицы или, возможно, внутреннего запроса, и вставлять результаты в таблицу с именем TABLE_NAME, которая имеет уникальное ограничение для столбца с именем IDX_COL_NAME.

INSERT /*+ ignore_row_on_dupkey_index(TABLE_NAME(IDX_COL_NAME)) */ 
INTO TABLE_NAME(
    INDEX_COL_NAME
  , col_1
  , col_2
  , col_3
  , ...
  , col_n)
SELECT 
    INDEX_COL_NAME
  , col_1
  , col_2
  , col_3
  , ...
  , col_n);

Это не очень хорошее решение, если ваша цель - поймать и обработать (то есть распечатать или обновить строку, которая нарушает ограничение). Но если вы просто хотели поймать это и проигнорировать нарушающий ряд, тогда это должно сработать.