Skip to Main Content
  • Questions
  • ORA-06531: Reference to uninitialized collection

Breadcrumb

Question and Answer

Connor McDonald

Thanks for the question, Malcolm.

Asked: April 27, 2016 - 1:54 pm UTC

Last updated: April 28, 2016 - 3:41 pm UTC

Version: 11.2.0.3.0

Viewed 10K+ times! This question is

You Asked

Hi, I have the following test code that is giving the issue mentioned above - I've reviewed other threads given on this issue and managed to nearly get it working but having 2 issues as mentioned in the questions below - In this simple example, I've just 1 header record with 4 lines but in reality there will be many headers with differing number of lines

Effectively, I'm trying to build a PLSQL Table TYPE array from the records in the STAGING table for then passing into another program

-------------------------------------

drop package body TEST;
drop package TEST;
drop TYPE TEST_HEADER_TYPE;
drop TYPE TEST_HEADER_OBJ;
drop TYPE TEST_LINE_TYPE;
drop TYPE TEST_LINE_OBJ;
drop table TEST_HEADER_STAGING;
drop table TEST_LINE_STAGING;

set serverout on size 999999;

create or replace TYPE TEST_LINE_OBJ is object (line_id number, col1 varchar2(100));
/
create or replace TYPE TEST_LINE_TYPE is table of TEST_LINE_OBJ;
/

create or replace TYPE TEST_HEADER_OBJ is object (header_id number, col1 varchar2(100),

line_info TEST_LINE_TYPE);
/
create or replace TYPE TEST_HEADER_TYPE is table of TEST_HEADER_OBJ;
/
create table TEST_HEADER_STAGING (header_index number, col1 varchar2(100));

create table TEST_LINE_STAGING (header_index number, line_index number, col1 varchar2

(100));

insert into TEST_HEADER_STAGING (header_index, col1) values (1, 'invoice1');
insert into TEST_LINE_STAGING (header_index, line_index, col1) values (1,1,'line1');
insert into TEST_LINE_STAGING (header_index, line_index, col1) values(1,2,'line2');
insert into TEST_LINE_STAGING (header_index, line_index, col1) values(1,3,'line3');
insert into TEST_LINE_STAGING (header_index, line_index, col1) values(1,4,'line4');
commit;

create or replace PACKAGE TEST AS
PROCEDURE TEST;
END;
/

create or replace PACKAGE BODY TEST AS
PROCEDURE TEST IS

acc_header TEST_HEADER_TYPE := TEST_HEADER_TYPE();
acc_line TEST_LINE_TYPE := TEST_LINE_TYPE();

CURSOR cur_get_headers IS
select header_index, col1
from test_header_staging
order by header_index;

CURSOR cur_get_lines IS
select header_index, line_index, col1
from test_line_staging
order by header_index, line_index;

BEGIN

acc_header := TEST_HEADER_TYPE(null);
acc_line := TEST_LINE_TYPE(null);

FOR hrec IN cur_get_headers LOOP

FOR lrec IN cur_get_lines LOOP

acc_line.extend;
acc_line(lrec.line_index) := TEST_LINE_OBJ(lrec.line_index,lrec.col1);

END LOOP;

acc_header.extend;
acc_header(hrec.header_index) := TEST_HEADER_OBJ(hrec.header_index,
hrec.col1,
TEST_LINE_TYPE(acc_line(1), <-- How do I not hard code these lines
acc_line(2), <-- as the number will change per Invoice Header
acc_line(3),
acc_line(4)));

END LOOP;

FOR i IN acc_header.FIRST .. acc_header.LAST LOOP

dbms_output.put_line('Header ID = '||acc_header(i).header_id);
dbms_output.put_line('Header Col1 = '||acc_header(i).col1);
dbms_output.put_line('Line ID = '||acc_header(i).line_info(1).line_id);
dbms_output.put_line('Line Col1 = '||acc_header(i).line_info(1).col1);
dbms_output.put_line('Line ID = '||acc_header(i).line_info(2).line_id);
dbms_output.put_line('Line Col1 = '||acc_header(i).line_info(2).col1);
dbms_output.put_line('Line ID = '||acc_header(i).line_info(3).line_id);
dbms_output.put_line('Line Col1 = '||acc_header(i).line_info(3).col1);
dbms_output.put_line('Line ID = '||acc_header(i).line_info(4).line_id);
dbms_output.put_line('Line Col1 = '||acc_header(i).line_info(4).col1);

END LOOP;

END;
END;
/

show error

exec test.test

------------------------------------------------

This gives results

Header ID = 1
Header Col1 = invoice1
Line ID = 1
Line Col1 = line1
Line ID = 2
Line Col1 = line2
Line ID = 3
Line Col1 = line3
Line ID = 4
Line Col1 = line4
Header ID =
Header Col1 =
BEGIN test.test; END;

*
ERROR at line 1:
ORA-06531: Reference to uninitialized collection
ORA-06512: at "APPS.TEST", line 45
ORA-06512: at line 1

-------------------------------------------------------

Questions
1. Why is there an additional NULL element in the HEADER array ?
2. How can I populate the lines embedded in the header Object Type without hard coding the number of lines ? In this example, I've just 4 lines
but I won't know how many are usually in the Line Staging table for each header.

and Connor said...

1) Because x := nested_table(null) is not the same as x:= nested_table();
2) You dont need to.. you just assign the whole array


SQL>
SQL> drop package body TEST;

Package body dropped.

SQL> drop package TEST;

Package dropped.

SQL> drop TYPE TEST_HEADER_TYPE;

Type dropped.

SQL> drop TYPE TEST_HEADER_OBJ;

Type dropped.

SQL> drop TYPE TEST_LINE_TYPE;

Type dropped.

SQL> drop TYPE TEST_LINE_OBJ;

Type dropped.

SQL> drop table TEST_HEADER_STAGING purge;

Table dropped.

SQL> drop table TEST_LINE_STAGING purge;

Table dropped.

SQL>
SQL> set serverout on size 999999;
SQL> create or replace TYPE TEST_LINE_OBJ is object (line_id number, col1 varchar2(100));
  2  /

Type created.

SQL>
SQL> create or replace TYPE TEST_LINE_TYPE is table of TEST_LINE_OBJ;
  2  /

Type created.

SQL>
SQL> create or replace TYPE TEST_HEADER_OBJ is object (header_id number, col1 varchar2(100),
  2  line_info TEST_LINE_TYPE);
  3  /

Type created.

SQL>
SQL> create or replace TYPE TEST_HEADER_TYPE is table of TEST_HEADER_OBJ;
  2  /

Type created.

SQL>
SQL> create table TEST_HEADER_STAGING (header_index number, col1 varchar2(100));

Table created.

SQL>
SQL> create table TEST_LINE_STAGING (header_index number, line_index number, col1 varchar2(100));

Table created.

SQL>
SQL> insert into TEST_HEADER_STAGING (header_index, col1) values (1, 'invoice1');

1 row created.

SQL> insert into TEST_LINE_STAGING (header_index, line_index, col1) values (1,1,'line1');

1 row created.

SQL> insert into TEST_LINE_STAGING (header_index, line_index, col1) values(1,2,'line2');

1 row created.

SQL> insert into TEST_LINE_STAGING (header_index, line_index, col1) values(1,3,'line3');

1 row created.

SQL> insert into TEST_LINE_STAGING (header_index, line_index, col1) values(1,4,'line4');

1 row created.

SQL> commit;

Commit complete.

SQL>
SQL>
SQL>
SQL> create or replace PACKAGE TEST AS
  2  PROCEDURE TEST;
  3  END;
  4  /

Package created.

SQL>
SQL>
SQL>
SQL> create or replace PACKAGE BODY TEST AS
  2
  3  PROCEDURE TEST IS
  4  acc_header TEST_HEADER_TYPE := TEST_HEADER_TYPE();
  5  acc_line TEST_LINE_TYPE := TEST_LINE_TYPE();
  6
  7  CURSOR cur_get_headers IS
  8  select header_index, col1
  9  from test_header_staging
 10  order by header_index;
 11
 12  CURSOR cur_get_lines IS
 13  select header_index, line_index, col1
 14  from test_line_staging
 15  order by header_index, line_index;
 16
 17
 18
 19  BEGIN
 20
 21  acc_header := TEST_HEADER_TYPE();
 22  acc_line := TEST_LINE_TYPE();
 23
 24  FOR hrec IN cur_get_headers LOOP
 25     FOR lrec IN cur_get_lines LOOP
 26       acc_line.extend;
 27       acc_line(lrec.line_index) := TEST_LINE_OBJ(lrec.line_index,lrec.col1);
 28     END LOOP;
 29
 30     acc_header.extend;
 31     acc_header(hrec.header_index) :=
 32       TEST_HEADER_OBJ(hrec.header_index,
 33                       hrec.col1,
 34                       acc_line
 35  );
 36
 37  END LOOP;
 38
 39  FOR i IN acc_header.FIRST .. acc_header.LAST LOOP
 40
 41  dbms_output.put_line('Header ID = '||acc_header(i).header_id);
 42  dbms_output.put_line('Header Col1 = '||acc_header(i).col1);
 43  dbms_output.put_line('Line ID = '||acc_header(i).line_info(1).line_id);
 44  dbms_output.put_line('Line Col1 = '||acc_header(i).line_info(1).col1);
 45  dbms_output.put_line('Line ID = '||acc_header(i).line_info(2).line_id);
 46  dbms_output.put_line('Line Col1 = '||acc_header(i).line_info(2).col1);
 47  dbms_output.put_line('Line ID = '||acc_header(i).line_info(3).line_id);
 48  dbms_output.put_line('Line Col1 = '||acc_header(i).line_info(3).col1);
 49  dbms_output.put_line('Line ID = '||acc_header(i).line_info(4).line_id);
 50  dbms_output.put_line('Line Col1 = '||acc_header(i).line_info(4).col1);
 51
 52  END LOOP;
 53  END;
 54
 55  END;
 56
 57  /

Package body created.

SQL>
SQL> show error
No errors.
SQL> exec test.test
Header ID = 1
Header Col1 = invoice1
Line ID = 1
Line Col1 = line1
Line ID = 2
Line Col1 = line2
Line ID = 3
Line Col1 = line3
Line ID = 4
Line Col1 = line4

PL/SQL procedure successfully completed.

SQL>
SQL>


Or, if you're not getting paid by the line of code :-) you could do this


SQL> create or replace PACKAGE BODY TEST AS
  2
  3  PROCEDURE TEST IS
  4  acc_header TEST_HEADER_TYPE := TEST_HEADER_TYPE();
  5  begin
  6  select TEST_HEADER_OBJ(hrec.header_index,
  7                       hrec.col1,
  8                       cast(multiset(
  9                          select TEST_LINE_OBJ(lrec.line_index,lrec.col1)
 10                          from test_line_staging lrec) as TEST_LINE_TYPE)
 11                      )
 12  bulk collect into   acc_header
 13  from test_header_staging hrec
 14  order by header_index;
 15
 16  FOR i IN acc_header.FIRST .. acc_header.LAST LOOP
 17
 18  dbms_output.put_line('Header ID = '||acc_header(i).header_id);
 19  dbms_output.put_line('Header Col1 = '||acc_header(i).col1);
 20  dbms_output.put_line('Line ID = '||acc_header(i).line_info(1).line_id);
 21  dbms_output.put_line('Line Col1 = '||acc_header(i).line_info(1).col1);
 22  dbms_output.put_line('Line ID = '||acc_header(i).line_info(2).line_id);
 23  dbms_output.put_line('Line Col1 = '||acc_header(i).line_info(2).col1);
 24  dbms_output.put_line('Line ID = '||acc_header(i).line_info(3).line_id);
 25  dbms_output.put_line('Line Col1 = '||acc_header(i).line_info(3).col1);
 26  dbms_output.put_line('Line ID = '||acc_header(i).line_info(4).line_id);
 27  dbms_output.put_line('Line Col1 = '||acc_header(i).line_info(4).col1);
 28
 29  END LOOP;
 30  END;
 31
 32  END;
 33
 34  /

Package body created.

SQL>
SQL> show error
No errors.
SQL> exec test.test
Header ID = 1
Header Col1 = invoice1
Line ID = 1
Line Col1 = line1
Line ID = 2
Line Col1 = line2
Line ID = 3
Line Col1 = line3
Line ID = 4
Line Col1 = line4

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