G-4350: Always use 1 as lower and COUNT() as upper bound when looping through a dense array.
Major
Reliability
Reason
Doing so will not raise a VALUE_ERROR
if the array you are looping through is empty. If you want to use FIRST()..LAST()
you need to check the array for emptiness beforehand to avoid the raise of VALUE_ERROR
.
Example (bad)
DECLARE
TYPE t_employee_type IS TABLE OF employees.employee_id%TYPE;
t_employees t_employee_type := t_employee_type();
BEGIN
<<process_employees>>
FOR i IN t_employees.FIRST()..t_employees.LAST()
LOOP
sys.dbms_output.put_line(t_employees(i)); -- some processing
END LOOP process_employees;
END;
/
Example (better)
Raise an unitialized collection error if t_employees
is not initialized.
DECLARE
TYPE t_employee_type IS TABLE OF employees.employee_id%TYPE;
t_employees t_employee_type := t_employee_type();
BEGIN
<<process_employees>>
FOR i IN 1..t_employees.COUNT()
LOOP
sys.dbms_output.put_line(t_employees(i)); -- some processing
END LOOP process_employees;
END;
/
Example (good)
Raises neither an error nor checking whether the array is empty. t_employees.COUNT()
always returns a NUMBER
(unless the array is not initialized). If the array is empty COUNT()
returns 0 and therefore the loop will not be entered.
DECLARE
TYPE t_employee_type IS TABLE OF employees.employee_id%TYPE;
t_employees t_employee_type := t_employee_type();
BEGIN
IF t_employees IS NOT NULL THEN
<<process_employees>>
FOR i IN 1..t_employees.COUNT()
LOOP
sys.dbms_output.put_line(t_employees(i)); -- some processing
END LOOP process_employees;
END IF;
END;
/