Я хочу воспользоваться преимуществами массовых операций Oracle DML и обработки исключений. Мое требование - выполнить операцию DML в представлении базы данных, где он выполняет некоторые проверки с помощью триггера представления, а затем, наконец, вставляет / обновляет базовую таблицу. Однако Oracle FORALL .. SAVE EXCEPTIONS, похоже, не улавливает ошибку проверки, возникающую в представлении. Это ограничение / ограничение SAVE EXCEPTION, когда оно работает только с таблицей базы данных, но не с просмотром? Документация Oracle, похоже, тоже не упоминает об этом. Ниже приведены мои тестовые коды (на основе модификации Обработка исключений в массовых операциях):
Создать таблицу:
create table exception_test (
id number(10) not null
);
Создайте представление на столе:
create or replace view exception_test_v as
select exception_test.id id
,sysdate daytime
from exception_test;
Создайте триггер в представлении:
create or replace trigger iud_exception_test
instead of insert or update or delete on exception_test_v
for each row
declare
begin
if inserting then
if nvl(:new.id, 0) = 0 then
RAISE_APPLICATION_ERROR(-20815, 'ID must not be null!');
end if;
insert into exception_test (id) values (:new.id);
end if;
end;
/
Тестовый код DML в представлении базы данных:
declare
TYPE t_tab IS TABLE OF exception_test_v%ROWTYPE;
l_tab t_tab := t_tab();
l_error_count NUMBER;
ex_dml_errors EXCEPTION;
PRAGMA EXCEPTION_INIT(ex_dml_errors, -24381);
BEGIN
-- Fill the collection.
FOR i IN 1 .. 100 LOOP
l_tab.extend;
l_tab(l_tab.last).id := i;
END LOOP;
-- Cause a failure.
l_tab(50).id := NULL;
l_tab(51).id := NULL;
EXECUTE IMMEDIATE 'TRUNCATE TABLE exception_test';
-- Perform a bulk operation.
BEGIN
FORALL i IN l_tab.first .. l_tab.last SAVE EXCEPTIONS
INSERT INTO exception_test_v (id)
VALUES (l_tab(i).id);
EXCEPTION
WHEN ex_dml_errors THEN
l_error_count := SQL%BULK_EXCEPTIONS.count;
DBMS_OUTPUT.put_line('Number of failures: ' || l_error_count);
FOR i IN 1 .. l_error_count LOOP
DBMS_OUTPUT.put_line('Error: ' || i ||
' Array Index: ' || SQL%BULK_EXCEPTIONS(i).error_index ||
' Message: ' || SQLERRM(-SQL%BULK_EXCEPTIONS(i).ERROR_CODE));
END LOOP;
END;
END;
Ошибка тестового кода в индексе 50 из триггера представления вместо обработки полных 100 вставок и перехвата ошибок в индексах 50 и 51 для последующей проверки.
Мы будем благодарны за любые отзывы об этом!
ORA-20815
из триггера вместоORA-24381
изSAVE EXCEPTIONS
. Поэтому я не могу перехватывать исключения сразу, потому что операцияFORALL
немедленно выдаст ошибку. - person Potoroo   schedule 07.10.2014