Nad Ghantous
Nad Ghantous

Reputation: 1

How to use index by table collections in PL/SQL

I am a new user to PL/SQL and recently created an account in Stack Overflow. I am trying to use one loop to retrieve data and store it in an index by table, and then another loop to display the data from the index by table, but it keeps giving me an error that the data is not found. Here is my code:

    SET SERVEROUTPUT ON
    DECLARE
      TYPE dept_table_type IS TABLE OF departments.department_name%TYPE INDEX BY PLS_INTEGER;
      my_dept_table dept_table_type;
      loop_count NUMBER := 10;
      deptno NUMBER := 10;
    BEGIN
      dbms_output.put_line('DEPARTMENT_ID                  DEPARTMENT_NAME');
      LOOP
        SELECT department_name INTO my_dept_table(loop_count)
        FROM departments
        WHERE department_id = deptno;

        deptno := deptno + 10;
        loop_count := loop_count + 10;

        EXIT WHEN loop_count > 100;
      END LOOP;

      FOR I in my_dept_table.FIRST..my_dept_table.LAST
      LOOP
        DBMS_OUTPUT.PUT_LINE(I||'                                   '||my_dept_table(I));
      END LOOP;
    END;
    /


    Result: Error report -
    ORA-01403: no data found
    ORA-06512: at line 18
    01403. 00000 -  "no data found"
    *Cause:    No data was found from the objects.
    *Action:   There was no data from the objects which may be due to end of fetch.

Can anyone please check the code. I am a new user to PLSQL and Thank you.

Upvotes: 0

Views: 1444

Answers (1)

Littlefoot
Littlefoot

Reputation: 142743

There are two suspicious places which can cause the NO_DATA_FOUND exception.

The first one is select statement which would fail if you try to fetch department name that belongs to department number which doesn't exist.

Based on Scott's DEPT table (as I don't have your tables): this is table's contents:

SQL> select * from dept;

    DEPTNO DNAME                LOC
---------- -------------------- --------------------
        10 ACCOUNTING           NEW YORK
        20 RESEARCH             DALLAS
        30 SALES                CHICAGO
        40 OPERATIONS           BOSTON

Your code, rewritten:

SQL> set serveroutput on
SQL>
SQL> DECLARE
  2     TYPE dept_table_type IS TABLE OF dept.dname%TYPE
  3        INDEX BY PLS_INTEGER;
  4
  5     my_dept_table  dept_table_type;
  6     l_deptno       NUMBER := 10;
  7  BEGIN
  8     LOOP
  9        DBMS_OUTPUT.put_line (l_deptno);
 10
 11        SELECT dname                             --> this fails
 12          INTO my_dept_table (l_deptno)
 13          FROM dept
 14         WHERE deptno = l_deptno;
 15
 16        l_deptno := l_deptno + 10;
 17        EXIT WHEN l_deptno > 100;
 18     END LOOP;
 19  END;
 20  /
10
20
30
40
50                            --> because department 50 doesn't exist
DECLARE
*
ERROR at line 1:
ORA-01403: no data found
ORA-06512: at line 11

So, what to do? Handle the exception!

SQL> DECLARE
  2     TYPE dept_table_type IS TABLE OF dept.dname%TYPE
  3        INDEX BY PLS_INTEGER;
  4
  5     my_dept_table  dept_table_type;
  6     l_deptno       NUMBER := 10;
  7  BEGIN
  8     LOOP
  9        DBMS_OUTPUT.put_line (l_deptno);
 10
 11        BEGIN
 12           SELECT dname
 13             INTO my_dept_table (l_deptno)
 14             FROM dept
 15            WHERE deptno = l_deptno;
 16        EXCEPTION
 17           WHEN NO_DATA_FOUND
 18           THEN
 19              DBMS_OUTPUT.put_line (l_deptno || ' department does not exist');
 20        END;
 21
 22        l_deptno := l_deptno + 10;
 23        EXIT WHEN l_deptno > 100;
 24     END LOOP;
 25  END;
 26  /
10
20
30
40
50
50 department does not exist
60
60 department does not exist
70
70 department does not exist
80
80 department does not exist
90
90 department does not exist
100
100 department does not exist

PL/SQL procedure successfully completed.

SQL>

Another place (which is what your code suffers from) is when you try to display array item that doesn't exist.

SQL> DECLARE
  2     TYPE dept_table_type IS TABLE OF dept.dname%TYPE
  3        INDEX BY PLS_INTEGER;
  4
  5     my_dept_table  dept_table_type;
  6     l_deptno       NUMBER := 10;
  7  BEGIN
  8     LOOP
  9        BEGIN
 10           SELECT dname
 11             INTO my_dept_table (l_deptno)
 12             FROM dept
 13            WHERE deptno = l_deptno;
 14        EXCEPTION
 15           WHEN NO_DATA_FOUND
 16           THEN
 17              NULL;
 18        END;
 19
 20        l_deptno := l_deptno + 10;
 21        EXIT WHEN l_deptno > 100;
 22     END LOOP;
 23
 24     DBMS_OUTPUT.put_line ('Number of items: ' || my_dept_table.COUNT);
 25
 26     FOR I IN my_dept_table.FIRST .. my_dept_table.LAST
 27     LOOP
 28        DBMS_OUTPUT.put_line ('i = ' || i);
 29        DBMS_OUTPUT.put_line (my_dept_table (i));
 30     END LOOP;
 31  END;
 32  /
Number of items: 4             --> department numbers 10, 20, 30, 40
i = 10                         --> this is OK - department 10 = ACCOUNTING
ACCOUNTING
i = 11                         --> but, there's no department 11 and you got an error
DECLARE
*
ERROR at line 1:
ORA-01403: no data found
ORA-06512: at line 29


SQL>

Suggestion: rewrite code entirely to be more efficient:

SQL> DECLARE
  2     TYPE dept_table_type IS TABLE OF dept.dname%TYPE
  3        INDEX BY PLS_INTEGER;
  4
  5     my_dept_table  dept_table_type;
  6  BEGIN
  7     SELECT dname
  8       BULK COLLECT INTO my_dept_table
  9       FROM dept;
 10
 11     FOR i IN my_dept_table.FIRST .. my_dept_table.LAST
 12     LOOP
 13        DBMS_OUTPUT.put_line (my_dept_table (i));
 14     END LOOP;
 15  END;
 16  /
ACCOUNTING
RESEARCH
SALES
OPERATIONS

PL/SQL procedure successfully completed.

SQL>

Upvotes: 2

Related Questions