Reputation: 303
The following block compiles correctly .(Unimportant parts redacted)
CREATE OR REPLACE PROCEDURE testProc
IS
TYPE test_h IS TABLE OF VARCHAR2(100) INDEX BY VARCHAR2(100);
test_h_list test_h;
TYPE l_ids IS TABLE OF VARCHAR(100);
l_id_list l_ids;
BEGIN
test_h_list('A'):='Apple';
test:=test_h_list.FIRST;
WHILE test IS NOT NULL LOOP
BEGIN
SELECT tbl1.l_id BULK COLLECT INTO l_id_list
WHERE ....
....
....
END;
However, when I attempt to convert it into a plsql block
DECLARE
TYPE test_h IS TABLE OF VARCHAR2(100) INDEX BY VARCHAR2(100);
test_h_list test_h; --ORA-06531: Reference to uninitialized collection :-(
TYPE l_ids IS TABLE OF VARCHAR(100);
l_id_list l_ids;
BEGIN
test_h_list('A'):='Apple';
test:=test_h_list.FIRST;
WHILE test IS NOT NULL LOOP
BEGIN
SELECT tbl1.l_id BULK COLLECT INTO l_id_list
WHERE ....
....
....
END;
I get the 'ORA-06531: Reference to uninitialized collection ' error as annotated above. I tried searching around and came across this and based on the examples here
I came up with this
DECLARE
TYPE test_h IS TABLE OF VARCHAR2(100) INDEX BY VARCHAR2(100);
test_h_list test_h := test_h();
TYPE l_ids IS TABLE OF VARCHAR(100);
l_id_list l_ids :=l_ids();
BEGIN
test_h_list.EXTEND(100);
l_ids.EXTEND(100);
test_h_list('A'):='Apple';
test:=test_h_list.FIRST;
WHILE test IS NOT NULL LOOP
BEGIN
SELECT tbl1.l_id BULK COLLECT INTO l_id_list
WHERE ....
....
....
END;
But this throws an error saying PLS-00222: no function with name 'test_h' exists in this scope. Any idea on what I might be missing?
MCVE
Script -
DECLARE
TYPE test_h IS TABLE OF VARCHAR2(100) INDEX BY VARCHAR2(100);
test_h_list test_h := test_h(); --Line 3
TYPE l_ids IS TABLE OF VARCHAR(100);
l_id_list l_ids := l_ids();
test_str VARCHAR(50);
BEGIN
test_h_list.EXTEND(100);
l_id_list.EXTEND(100);
test_h_list('App'):='1';
test_h_list('Red'):='2';
test_str:=test_h_list.FIRST;
WHILE test_str IS NOT NULL LOOP
BEGIN
SELECT TABLE1.DEPT BULK COLLECT INTO l_id_list
FROM TABLE1
WHERE TABLE1.NAME = test_str;
FOR indx IN 1..l_id_list.COUNT
LOOP
DBMS_OUTPUT.PUT_LINE( l_id_list(indx));
END LOOP;
test_str:=test_h_list.NEXT(test_str);
EXCEPTION
WHEN OTHERS THEN -- Just print the failure to logs
NULL;
END;
END LOOP;
END;
/
Error Report -
Error starting at line 1 in command:
DECLARE
TYPE test_h IS TABLE OF VARCHAR2(100) INDEX BY VARCHAR2(100);
test_h_list test_h := test_h();
TYPE l_ids IS TABLE OF VARCHAR(100);
l_id_list l_ids := l_ids();
test_str VARCHAR(50);
BEGIN
test_h_list.EXTEND(100);
l_id_list.EXTEND(100);
test_h_list('App'):='1';
test_h_list('Red'):='2';
test_str:=test_h_list.FIRST;
WHILE test_str IS NOT NULL LOOP
BEGIN
SELECT TABLE1.DEPT BULK COLLECT INTO l_id_list
FROM TABLE1
WHERE TABLE1.NAME = test_str;
FOR indx IN 1..l_id_list.COUNT
LOOP
DBMS_OUTPUT.PUT_LINE( l_id_list(indx));
END LOOP;
test_str:=test_h_list.NEXT(test_str);
EXCEPTION
WHEN OTHERS THEN
NULL;
END;
END LOOP;
END;
Error report:
ORA-06550: line 3, column 23:
PLS-00222: no function with name 'TEST_H' exists in this scope
ORA-06550: line 3, column 13:
PL/SQL: Item ignored
ORA-06550: line 9, column 3:
PLS-00320: the declaration of the type of this expression is incomplete or malformed
ORA-06550: line 9, column 3:
PL/SQL: Statement ignored
ORA-06550: line 11, column 3:
PLS-00320: the declaration of the type of this expression is incomplete or malformed
ORA-06550: line 11, column 3:
PL/SQL: Statement ignored
ORA-06550: line 12, column 3:
PLS-00320: the declaration of the type of this expression is incomplete or malformed
ORA-06550: line 12, column 3:
PL/SQL: Statement ignored
ORA-06550: line 13, column 13:
PLS-00320: the declaration of the type of this expression is incomplete or malformed
ORA-06550: line 13, column 3:
PL/SQL: Statement ignored
ORA-06550: line 27, column 15:
PLS-00320: the declaration of the type of this expression is incomplete or malformed
ORA-06550: line 27, column 5:
PL/SQL: Statement ignored
06550. 00000 - "line %s, column %s:\n%s"
*Cause: Usually a PL/SQL compilation error.
*Action:
Elapsed: 00:00:00.011
Upvotes: 2
Views: 382
Reputation: 191235
In your MCVE you're mixing up different types of PL/SQL table. Your test_h
types is indexed so doesn't need to be initialized and can't be extended - since it's a sparse table type. So removing the := test_h()
and the extend
line makes this work:
DECLARE
TYPE test_h IS TABLE OF VARCHAR2(100) INDEX BY VARCHAR2(100);
test_h_list test_h; -- do no instantiate := test_h(); --Line 3
TYPE l_ids IS TABLE OF VARCHAR(100);
l_id_list l_ids := l_ids();
test_str VARCHAR(50);
BEGIN
-- test_h_list.EXTEND(100); -- do not extend either
l_id_list.EXTEND(100);
test_h_list('App'):='1';
test_h_list('Red'):='2';
test_str:=test_h_list.FIRST;
WHILE test_str IS NOT NULL LOOP
BEGIN
SELECT TABLE1.DEPT BULK COLLECT INTO l_id_list
FROM TABLE1
WHERE TABLE1.NAME = test_str;
FOR indx IN 1..l_id_list.COUNT
LOOP
DBMS_OUTPUT.PUT_LINE( l_id_list(indx));
END LOOP;
test_str:=test_h_list.NEXT(test_str);
EXCEPTION
WHEN OTHERS THEN -- Just print the failure to logs
NULL;
END;
END LOOP;
END;
/
PL/SQL procedure successfully completed.
Your original first anonymous block wasn't doing either of those things, and had the same sparse table type for test_h
, so should not have been getting the ORA-06531. You would have seen it if you'd removed the INDEX BY VARCHAR2(100)
from the type definition, but that isn't what you showed.
You could also have got it from trying to refer to elements of l_id_list
without initialising that - but as presented in the question, it would always have been initalized implicitly by the bulk collect in the loop, even if the real table being queried was empty - you'd just have an empty PL/SQL table.
The code you originally showed doesn't throw the error; and the MCVE is doing something different, closer to your second anonymous block than the first one.
Upvotes: 1