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