ORA-06530: "引用未初始化的复合" 即使已初始化
Posted
技术标签:
【中文标题】ORA-06530: "引用未初始化的复合" 即使已初始化【英文标题】:ORA-06530: "Reference to uninitialized composite" even if initialized 【发布时间】:2016-01-07 08:15:13 【问题描述】:我已阅读解决错误的解决方案,但我不知道为什么仍然会出现错误,
CREATE OR REPLACE TYPE tmp_object IS OBJECT (
id NUMBER,
code NUMBER
);
CREATE OR REPLACE TYPE tmp_table IS TABLE OF tmp_object;
以及使用它们的匿名块:
DECLARE
cnt PLS_INTEGER;
tmp_tbl tmp_table := tmp_table();
BEGIN
SELECT regexp_count('34, 87, 908, 123, 645', '[^,]+', 1) str
INTO cnt
FROM dual;
DBMS_OUTPUT.PUT_LINE('Counter is: ' || cnt);
FOR i IN 1..cnt
LOOP
tmp_tbl.EXTEND;
SELECT TRIM(REGEXP_SUBSTR('34, 87, 908, 123, 645', '[^,]+', 1,i)) str
INTO tmp_tbl(tmp_tbl.LAST).code
FROM dual;
DBMS_OUTPUT.PUT_LINE(tmp_tbl(i).code);
END LOOP;
END;
我使用的是Oracle Database 12c及以下是SQL Developer 4.2的错误:
错误报告 -
ORA-06530:对未初始化复合的引用
ORA-06512:在第 14 行
00000 - “引用未初始化的复合”
*原因:对象、LOB 或其他组合被引用为 左侧未初始化。
*Action:使用适当的构造函数初始化组合 或整个对象分配。
【问题讨论】:
你当时没有LAST数据标签,所以没有初始化 【参考方案1】:您使用的语法适用于记录
SQL> set serverout on;
SQL>
SQL> DECLARE
2 cnt PLS_INTEGER;
3 l_code NUMBER;
4 TYPE tmp_object IS RECORD (
5 id NUMBER,
6 code NUMBER
7 );
8 TYPE tmp_table IS TABLE OF tmp_object;
9 tmp_tbl tmp_table := tmp_table();
10 BEGIN
11 SELECT regexp_count('34, 87, 908, 123, 645', '[^,]+', 1) str
12 INTO cnt
13 FROM dual;
14
15 DBMS_OUTPUT.PUT_LINE('Counter is: ' || cnt);
16
17 FOR i IN 1..cnt
18 LOOP
19 tmp_tbl.EXTEND;
20
21 SELECT TRIM(REGEXP_SUBSTR('34, 87, 908, 123, 645', '[^,]+', 1,i)) str
22 INTO tmp_tbl(tmp_tbl.LAST).code
23 FROM dual;
24 DBMS_OUTPUT.PUT_LINE(tmp_tbl(i).code);
25
26 END LOOP;
27 END;
28 /
Counter is: 5
34
87
908
123
645
PL/SQL procedure successfully completed
要使用 OBJECT,您必须使用对象构造函数插入该对象的表中
SQL>
SQL> CREATE OR REPLACE TYPE tmp_object IS OBJECT (
2 id NUMBER,
3 code NUMBER
4 );
5
6 /
Type created
SQL> CREATE OR REPLACE TYPE tmp_table IS TABLE OF tmp_object;
2 /
Type created
SQL>
SQL> DECLARE
2 cnt PLS_INTEGER;
3 tmp_tbl tmp_table := tmp_table();
4 BEGIN
5 SELECT regexp_count('34, 87, 908, 123, 645', '[^,]+', 1) str
6 INTO cnt
7 FROM dual;
8
9 DBMS_OUTPUT.PUT_LINE('Counter is: ' || cnt);
10
11 FOR i IN 1..cnt
12 LOOP
13 tmp_tbl.EXTEND;
14
15 SELECT tmp_object(i, TRIM(REGEXP_SUBSTR('34, 87, 908, 123, 645', '[^,]+', 1,i)))
16 INTO tmp_tbl(tmp_tbl.last)
17 FROM dual;
18
19 DBMS_OUTPUT.PUT_LINE(tmp_tbl(i).code);
20 END LOOP;
21 END;
22 /
Counter is: 5
34
87
908
123
645
PL/SQL procedure successfully completed
更新:在集合上打开光标
您必须使用引用游标从集合中收集值 使用 TABLE 函数和 CAST 函数帮助 oracle 识别 集合的数据类型。
SQL> DECLARE
2 cnt PLS_INTEGER;
3 tmp_tbl tmp_table := tmp_table();
4 c_cursor SYS_REFCURSOR;
5 l_id NUMBER;
6 l_code NUMBER;
7 BEGIN
8 SELECT regexp_count('34, 87, 908, 123, 645', '[^,]+', 1) str INTO cnt FROM dual;
9
10 dbms_output.put_line('Counter is: ' || cnt);
11
12 FOR i IN 1 .. cnt LOOP
13 tmp_tbl.extend;
14
15 SELECT tmp_object(i, TRIM(regexp_substr('34, 87, 908, 123, 645', '[^,]+', 1, i)))
16 INTO tmp_tbl(tmp_tbl.last)
17 FROM dual;
18
19 END LOOP;
20
21 OPEN c_cursor FOR
22 SELECT * FROM TABLE(CAST(tmp_tbl AS tmp_table));
23 LOOP
24 FETCH c_cursor
25 INTO l_id,
26 l_code;
27 EXIT WHEN c_cursor%NOTFOUND;
28 dbms_output.put_line(l_id || ',' || l_code);
29 END LOOP;
30 CLOSE c_cursor;
31
32 END;
33 /
Counter is: 5
1,34
2,87
3,908
4,123
5,645
PL/SQL procedure successfully completed
【讨论】:
现在如果我想从tmp_tbl
表中进行选择,我该怎么做? (将其获取到游标)
如何对这些集合类型的表进行 DML 操作?
您不能直接在集合类型上运行 DML。您必须找到要更新的记录的下标,然后使用相同的下标对其进行更新。例如 - tmp_tbl(i).code := 99;
其中i
是需要更新的记录的下标。
this link 是否在集合类型表上执行某种 DML?还是别的什么?
要重播您的上一条评论,我可以这样更新下标:tmp_tbl(i).code := tmp_tbl(i).code + 18;
,或者我必须像我提到的 oracle-base 链接那样做?跨度>
以上是关于ORA-06530: "引用未初始化的复合" 即使已初始化的主要内容,如果未能解决你的问题,请参考以下文章
C#自定义方法从dataset读到数组总提示未将对象引用设置到对象的实例 貌似是初始化的问题
(6个name="hobby"的复选项,两个按钮)来区分三种方法的不同---区别getElementByID,getElementsByName,getElem