Skip to Main Content
  • Questions
  • NO_DATA_FOUND exception when passing a empty row in associative array to procedure

Breadcrumb

Question and Answer

Connor McDonald

Thanks for the question, Matt.

Asked: January 31, 2018 - 8:20 pm UTC

Last updated: February 01, 2018 - 2:01 am UTC

Version: 11gr2

Viewed 1000+ times

You Asked

I am trying to pass a procedure a record that is, or will be rather a new row in an associative array but am getting a a NO_DATA_FOUND exception. When I set to position in the collection to NULL, it works fine.

Example simplified down:

-- spec
CREATE OR REPLACE PACKAGE PROCESS_DATE

IS

TYPE date_rec IS RECORD (
MyDate DATE
);

TYPE date_tbl IS TABLE OF date_rec INDEX BY PLS_INTEGER;

PROCEDURE PROCESS(date_r IN OUT date_rec); --, Clm IN OUT PKG_CNST.InType, Data IN OUT PKG_CNST.DataType, Rsp IN OUT PKG_CNST.OutType);

PROCEDURE TEST;

END PROCESS_DATE;
/

-- body
CREATE OR REPLACE PACKAGE BODY PROCESS_DATE

IS

PROCEDURE PROCESS(date_r IN OUT date_rec)

IS

BEGIN
date_r.MyDate := TRUNC(SYSDATE);


END PROCESS;

PROCEDURE TEST

IS

loc_date_tbl date_tbl;

BEGIN
FOR idx IN 1 .. 4 LOOP
PROCESS(loc_date_tbl(idx));
END LOOP;
END TEST;

END PROCESS_DATE;
/

-- test
BEGIN
process_date.test;
END;

so I have used examples of this at least I think I have where it works but in this case where I pass it off to a proc, I get a NO_DATA_FOUND exception

This is happening with tables within the record types too

IE:

TYPE artist_name IS TABLE OF VARCHAR2(30);

TYPE album_rec IS RECORD (
artist VARCHAR2(30),
ablum_title VARCHAR(2)
artist artist_name );

TYPE album_tbl IS TABLE OF album_rec INDEX BY PLS_INTEGER;

then access like

DELCARE
albums album_tbl
BEGIN
albums(albums.COUNT +1).artist(artist.COUNT + 1).artist_name := 'Matthew Good';
END;

In this example I am working with the whole parent table, I would typically be working with just one row of the parent table like above.



with LiveSQL Test Case:

and Connor said...

It is a bit of a chicken-and-egg situation here. You want to assign something to an array index entry but that array index entry might not exist yet.

So we simply add a check for that possibility

SQL> CREATE OR REPLACE PACKAGE PROCESS_DATE IS
  2      TYPE date_rec IS RECORD ( MyDate  DATE );
  3      TYPE date_tbl IS TABLE OF date_rec INDEX BY PLS_INTEGER;
  4
  5      PROCEDURE PROCESS(date_r IN OUT date_rec);
  6      PROCEDURE TEST;
  7
  8  END PROCESS_DATE;
  9  /

Package created.

SQL>
SQL> CREATE OR REPLACE PACKAGE BODY PROCESS_DATE IS
  2      PROCEDURE PROCESS(date_r IN OUT date_rec)     IS
  3      BEGIN
  4          date_r.MyDate := TRUNC(SYSDATE);
  5      END PROCESS;
  6
  7      PROCEDURE TEST     IS
  8          loc_date_tbl date_tbl;
  9      BEGIN
 10        dbms_output.put_line('Number of entries in array = '||loc_date_tbl.count);
 11
 12        FOR idx IN 1 ..4 LOOP
 13           IF NOT loc_date_tbl.exists(idx) then loc_date_tbl(idx) := null; end if;
 14           PROCESS(loc_date_tbl(idx));
 15        END LOOP;
 16
 17        dbms_output.put_line('Number of entries in array = '||loc_date_tbl.count);
 18      END TEST;
 19
 20  END PROCESS_DATE;
 21  /

Package body created.

SQL>
SQL> set serverout on
SQL> BEGIN
  2      process_date.test;
  3  END;
  4  /
Number of entries in array = 0
Number of entries in array = 4

PL/SQL procedure successfully completed.

SQL>
SQL>



Is this answer out of date? If it is, please let us know via a Comment

More to Explore

PL/SQL demos

Check out more PL/SQL tutorials on our LiveSQL tool.

PL/SQL docs

PL/SQL reference manual from the Oracle documentation library