如何将此过程正确转换为PLSQL块?对未初始化函数的引用
下面的块编译正确。(编辑了不重要的部分) 但是,当我尝试将其转换为plsql块时如何将此过程正确转换为PLSQL块?对未初始化函数的引用,sql,oracle,plsql,Sql,Oracle,Plsql,下面的块编译正确。(编辑了不重要的部分) 但是,当我尝试将其转换为plsql块时 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
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;
我得到了上面注释的“ORA-06531:Reference to uninitialized collection”错误。我试着四处搜索,发现并基于这些例子
我想到了这个
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;
但这会引发一个错误,即PLS-00222:此范围中不存在名为“test_h”的函数。你知道我遗漏了什么吗
MCVE
剧本-
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 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
在MCVE中,您混合了不同类型的PL/SQL表。您的
test\u h
类型已编制索引,因此不需要初始化,也无法扩展,因为它是稀疏表类型。因此,删除:=test_h()
和extend
行可以实现以下功能:
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.
您最初的第一个匿名块没有做这两件事,并且对于test_h
具有相同的稀疏表类型,因此不应该得到ORA-06531。如果您从类型定义中删除VARCHAR2(100)的索引,您可能会看到它,但这不是您显示的内容
您还可以通过尝试引用l_id_list
的元素而不进行初始化来获得它,但正如问题中所述,它总是由循环中的大容量收集隐式初始化,即使查询的实际表是空的,您只会有一个空的PL/SQL表
最初显示的代码不会抛出错误;MCVE正在做一些不同的事情,比第一个更接近您的第二个匿名块。我没有看到您的第一个匿名块中的错误-声明了test
并注释掉了循环,以及过程版本。您的过程是成功执行还是只是编译?你能把它转换成一个,并显示错误堆栈来确定哪一行实际抛出了错误吗?第二个匿名块中应出现错误。不管你在第一篇文章中做错了什么,似乎都是在你不幸编辑的代码中。@AlexPoole。。我将上传MCVE,但在此之前我有一个快速的问题-你使用的是什么版本的Oracle?根据问题中的链接,如果小于等于10,我不确定你是否会遇到这个问题。我在11.2.0.4中运行了它。您在哪个版本中看到错误?与test\u h\u list
相比,从l\u id\u list
的引用中得到错误的可能性更大,因为后者是索引的,不需要初始化。但您所显示的内容将始终初始化它,即使它是空的。这就是为什么需要一个可复制的例子。除了需要声明“test”这一事实之外,这对我来说是有效的。当你遇到“ORA-06531”错误时,你确定你有“VARCHAR2(100)”索引吗?如果省略了…
的索引,我可以看出您发布的代码(或多或少)可能会导致该错误。
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.