Искам да се възползвам от груповата DML операция на Oracle и обработката на изключения. Моето изискване е да изпълня DML операция на изглед на база данни, където изпълнява някои валидации чрез задействане на изглед, след което накрая вмъквам/актуализирам основната таблица. Въпреки това, FORALL .. SAVE EXCEPTIONS на Oracle изглежда не улавя грешка при валидиране, повдигната в изгледа. Това ли е ограничението/ограничението на 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