SET SERVEROUTPUT ON DECLARE TYPE t_tab IS TABLE OF exception_test%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 VALUES l_tab(i); 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; / Number of failures: 2 Error: 1 Array Index: 50 Message: ORA-01400: cannot insert NULL into () Error: 2 Array Index: 51 Message: ORA-01400: cannot insert NULL into () PL/SQL procedure successfully completed.
Friday, November 7, 2014
Save Exception or Bulk Exceptions in bulk collections
Bulk Binding concept with Example
The
FORALL
syntax allows us to bind the contents of a
collection to a single DML statement, allowing the DML to be run for
each row in the collection without requiring a context switch each time.
To test bulk binds using records we first create a test table.The following test compares the time taken to insert 10,000 rows using regularCREATE TABLE forall_test ( id NUMBER(10), code VARCHAR2(10), description VARCHAR2(50)); ALTER TABLE forall_test ADD ( CONSTRAINT forall_test_pk PRIMARY KEY (id)); ALTER TABLE forall_test ADD ( CONSTRAINT forall_test_uk UNIQUE (code));
FOR..LOOP
and a bulk bind.SET SERVEROUTPUT ON DECLARE TYPE t_forall_test_tab IS TABLE OF forall_test%ROWTYPE; l_tab t_forall_test_tab := t_forall_test_tab(); l_start NUMBER; l_size NUMBER := 10000; BEGIN -- Populate collection. FOR i IN 1 .. l_size LOOP l_tab.extend; l_tab(l_tab.last).id := i; l_tab(l_tab.last).code := TO_CHAR(i); l_tab(l_tab.last).description := 'Description: ' || TO_CHAR(i); END LOOP; EXECUTE IMMEDIATE 'TRUNCATE TABLE forall_test'; -- Time regular inserts. l_start := DBMS_UTILITY.get_time; FOR i IN l_tab.first .. l_tab.last LOOP INSERT INTO forall_test (id, code, description) VALUES (l_tab(i).id, l_tab(i).code, l_tab(i).description); END LOOP; DBMS_OUTPUT.put_line('Normal Inserts: ' || (DBMS_UTILITY.get_time - l_start)); EXECUTE IMMEDIATE 'TRUNCATE TABLE forall_test'; -- Time bulk inserts. l_start := DBMS_UTILITY.get_time; FORALL i IN l_tab.first .. l_tab.last INSERT INTO forall_test VALUES l_tab(i); DBMS_OUTPUT.put_line('Bulk Inserts : ' || (DBMS_UTILITY.get_time - l_start)); COMMIT; END; / Normal Inserts: 305 Bulk Inserts : 14 PL/SQL procedure successfully completed. SQL>
Bulk Collect concept with Example
SET SERVEROUTPUT ON DECLARE TYPE t_bulk_collect_test_tab IS TABLE OF bulk_collect_test%ROWTYPE; l_tab t_bulk_collect_test_tab := t_bulk_collect_test_tab(); l_start NUMBER; BEGIN -- Time a regular population. l_start := DBMS_UTILITY.get_time; FOR cur_rec IN (SELECT * FROM bulk_collect_test) LOOP l_tab.extend; l_tab(l_tab.last) := cur_rec; END LOOP; DBMS_OUTPUT.put_line('Regular (' || l_tab.count || ' rows): ' || (DBMS_UTILITY.get_time - l_start)); -- Time bulk population. l_start := DBMS_UTILITY.get_time; SELECT * BULK COLLECT INTO l_tab FROM bulk_collect_test; DBMS_OUTPUT.put_line('Bulk (' || l_tab.count || ' rows): ' || (DBMS_UTILITY.get_time - l_start)); END; / Regular (42578 rows): 66 Bulk (42578 rows): 4 PL/SQL procedure successfully completed. SQL>
Subscribe to:
Posts (Atom)