我想利用Oracle批量DML操作和異常處理。我的要求是在數據庫視圖上執行DML操作,通過視圖觸發器執行一些驗證,然後插入/更新基礎表。但是,Oracle的FORALL .. SAVE EXCEPTIONS似乎並未捕獲在視圖中引發的驗證錯誤。這是SAVE EXCEPTION的限制/限制,它只適用於數據庫表而不是查看? Oracle文檔似乎也沒有提到這一點。下面是我的測試代碼(基於改進自Handling Exceptions in Bulk Operations):Oracle 11gR2在數據庫視圖上FORALL SAVE EXCEPTIONS不起作用
創建表:
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;
/
create table exception_test (
id number(10) not null
);
在表上創建視圖
數據庫視圖上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上出錯,而不是在索引50和51上處理完整的100插入和捕獲錯誤以進行後期檢查。
對此的任何反饋將不勝感激!
可以執行單一測試插入視圖,並檢查是否異常升高引發的異常??? – psaraj12 2014-10-06 07:52:39
是的,使用我上面的測試代碼,引發的異常是來自觸發器的'ORA-20815',而不是'SAVE EXCEPTIONS'中的'ORA-24381'。因此我無法批量處理異常情況,因爲'FORALL'操作會立即出錯。 – Potoroo 2014-10-07 07:31:00