Avoiding Collection Exceptions
In many cases, if you reference a nonexistent collection element, then PL/SQL raises a predefined exception. Consider the illustration shown below:
DECLARE
TYPE NumList IS TABLE OF NUMBER;
nums NumList; -- atomically null
BEGIN
/* Assume execution continues despite the raised exceptions. */
nums(1) := 1; -- raises COLLECTION_IS_NULL (1)
nums := NumList(1,2); -- initialize table
nums(NULL) := 3 -- raises VALUE_ERROR (2)
nums(0) := 3; -- raises SUBSCRIPT_OUTSIDE_LIMIT (3)
nums(3) := 3; -- raises SUBSCRIPT_BEYOND_COUNT (4)
nums.DELETE(1); -- delete element 1
IF nums(1) = 1 THEN ... -- raises NO_DATA_FOUND (5)
In the first situation, the nested table is automatically null. In the second situation, the subscript is null. In the third situation, the subscript is outside the legal range. In the fourth situation, the subscripts exceed the number of elements in the table. In the fifth situation, the subscript designates a deleted element.
The list below shows when a given exception is raised:
In many cases, you can pass "invalid" subscripts to a method without raising the exception. For illustration, if you pass a null subscript to the procedure DELETE, it does nothing. You can also replace the deleted elements without raising NO_DATA_FOUND, as the example below shows:
DECLARE
TYPE NumList IS TABLE OF NUMBER;
nums NumList := NumList(10,20,30); -- initialize table
BEGIN
...
nums.DELETE(-1); -- does not raise SUBSCRIPT_OUTSIDE_LIMIT
nums.DELETE(3); -- delete 3rd element
DBMS_OUTPUT.PUT_LINE(nums.COUNT); -- prints 2
nums(3) := 30; -- legal; does not raise NO_DATA_FOUND
DBMS_OUTPUT.PUT_LINE(nums.COUNT); -- prints 3
END;
The Packaged collection types and the local collection types are never compatible. For example, assume that you want to call the following packaged process:
CREATE PACKAGE pkg1 AS
TYPE NumList IS VARRAY(25) OF NUMBER(4);
PROCEDURE delete_emps (emp_list NumList);
...
END pkg1;
CREATE PACKAGE BODY pkg1 AS
PROCEDURE delete_emps (emp_list NumList) IS ...
...
END pkg1;
If you run the PL/SQL block below, then the second procedure call fails with a wrong number or types of arguments error. This is because the packaged and local VARRAY types are incompatible even though their definitions are same.
DECLARE
TYPE NumList IS VARRAY(25) OF NUMBER(4);
emps pkg1.NumList := pkg1.NumList(7369, 7499);
emps2 NumList := NumList(7521, 7566);
BEGIN
pkg1.delete_emps(emps);
pkg1.delete_emps(emps2); -- causes a compilation error
END;