Systems Engineering and RDBMS

Bulk Collect and Multiple Exceptions

Posted by decipherinfosys on September 20, 2007

In one of our previous post, we had covered the scenario of getting a no data found exception when using Bulk Collect in PL/SQL.    In this post, we will look into how to handle multiple exceptions when using Bulk Collect.  BULK COLLECT construct is used to work with batches of data rather than single record at a time. Whenever we have to deal with large amount of data, bulk collect provides considerable performance improvement.

‘Bulk collect..into’ clause improve performance of the select statements. To loop through records collected using bulk collect we can use FORALL syntax. FORALL clause works with DML statements in batches and much faster than the regular for loop construct. In this blog post, we are going to talk about FORALL exceptions with the %BULK_EXCEPTIONS attribute. This attribute allows us to continue with the process, even if run into any DML exception for some record in between. Basically this mechanism allows us to complete the process without stopping if any error occurs.

All exceptions raised during execution are saved in %BULK_EXCEPTION attribute. It also stores a collection of records similar to BULK COLLECT. It has two fields.

•    %BULK_EXCEPTIONS(i).ERROR_CODE holds the corresponding Oracle error code.
•    %BULK_EXCEPTIONS(i).ERROR_INDEX holds the iteration number of the FORALL statement for which the exception was raised.
•    %BULK_EXCEPTIONS.COUNT holds total number of exceptions encountered.

In order to bulk collect exceptions, we have to use FORALL clause with SAVE EXCEPTIONS keyword. Let us see with the example.

Connect to SQL*Plus with proper credentials and run following query to create the table and populate it with some data.
CREATE TABLE TEST
(
Test_ID     NUMBER(9) NOT NULL PRIMARY KEY,
Test_Desc   VARCHAR(30),
New_Desc    VARCHAR(30)
)
/
SQL> INSERT INTO TEST(TEST_ID,TEST_DESC)
2  SELECT ROWNUM, TABLE_NAME
3    FROM USER_TABLES;

9 rows created.

Run following PL/SQL block to populate the table and later on update it to see the exception behavior. We have created this PL/SQL block based on the example shown in Oracle manual.

DECLARE

TYPE ga_Test_ID   IS TABLE OF TEST.TEST_Id%TYPE;
TYPE ga_Test_Desc IS TABLE OF TEST.TEST_DESC%TYPE;
va_Test_ID    ga_Test_ID;
va_Test_Desc  ga_Test_Desc;
V_Err_count   NUMBER;

BEGIN

SELECT Test_ID, Test_Desc
BULK COLLECT INTO va_Test_ID, va_Test_Desc
FROM Test;

FORALL i IN va_test_ID.FIRST..va_test_ID.LAST SAVE EXCEPTIONS
UPDATE TEST
SET NEW_DESC = TEST_DESC || LPAD(‘ ‘,22,’A’)
WHERE TEST_ID = va_test_ID(i);

EXCEPTION

WHEN OTHERS THEN

v_Err_Count := SQL%BULK_EXCEPTIONS.COUNT;
DBMS_OUTPUT.PUT_LINE(‘Number of statements that failed: ‘ || v_Err_Count);

FOR i IN 1..v_Err_Count
LOOP
DBMS_OUTPUT.PUT_LINE(‘Error #’ || i || ‘ occurred during ‘||
‘iteration #’ || SQL%BULK_EXCEPTIONS(i).ERROR_INDEX);
DBMS_OUTPUT.PUT_LINE(‘Error message is ‘ ||
SQLERRM(-SQL%BULK_EXCEPTIONS(i).ERROR_CODE));
END LOOP;
END;
/

If you execute above PL/SQL block, it will display following information. It may be different for your scenario as data will be different.

Number of statements that failed: 2
Error #1 occurred during iteration #6
Error message is ORA-12899: value too large for column
Error #2 occurred during iteration #9
Error message is ORA-12899: value too large for column

From above results we know that our iteration #6 and #9 failed because of the exceeding column length. This is really useful feature for error handling when we are dealing with larger data set. Instead of exiting at first error, we can loop through entire set and then work with the erroneous records later on.

One Response to “Bulk Collect and Multiple Exceptions”

  1. […] on November 29, 2007 In our previous blog posts, we had covered the scenarios of using multiple exceptions and using NO_DATA_FOUND exception when used with bulk collection. In this blog post, we will cover […]

Sorry, the comment form is closed at this time.

 
%d bloggers like this: