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

如何解决 Vue.js 中的“属性或方法未在实例上定义但在渲染期间引用..”?

引用未初始化的集合