使用游标将 Table 数据提取到 oracle 数据库中的 Varray

Fetching Table Data with Cursor to a Varray in oracle database

我有一个名为 PhoneBook 的 table,具有以下属性:ID、FirstName、LastName。它有5条记录 我想创建一个 VARRAY 并使用 Cursor 将 PhoneBook Table 中的所有 firstNames 提取到 VARRAY 中。这是我的代码:

DECLARE
    v_FirstName PHONEBOOK.FIRSTNAME%TYPE;
    TYPE arrayNames IS VARRAY(10) OF VARCHAR2(20);
    v1 arrayNames;
    i INT := 0;
    CURSOR c_phonebook IS SELECT FIRSTNAME FROM PHONEBOOK;
       BEGIN
           v1 := arrayNames(); 
           OPEN c_phonebook;
           LOOP
                FETCH c_phonebook INTO v_firstname;
                v1(i) := v_firstname;
                i := i+1;
                EXIT WHEN c_phonebook%NOTFOUND;
           END LOOP;

          CLOSE c_phonebook;

       END;/

当我编译这段代码时,它给了我一个错误:

ORA-06532: Subscript outside of limit ORA-06512: at line 14 06532. 00000 - "Subscript outside of limit" *Cause: A subscript was greater than the limit of a varray or non-positive for a varray or nested table. *Action: Check the program logic and increase the varray limit if necessary.

请帮我解决这个问题。谢谢

您需要增加数组的大小,创建一个您可以填充的空元素,每次您想要添加一个成员时:

...
BEGIN
    v1 := arrayNames();
    OPEN c_phonebook;
    LOOP
        FETCH c_phonebook INTO v_firstname;
        EXIT WHEN c_phonebook%NOTFOUND;
        i := i+1;
        v1.EXTEND();
        v1(i) := v_firstname;
    END LOOP;
    CLOSE c_phonebook;
END;

请注意,我已将 i := i+1 移动到赋值之前,因为数组是从 1 而不是 0 开始索引的。我还将 EXIT 移动到紧跟在 [= 之后15=],因此您不会尝试两次处理游标的最后一行。

本例中其实不需要i,可以使用数组的当前COUNT来标识新增条目:

DECLARE
    v_FirstName PHONEBOOK.FIRSTNAME%TYPE;
    TYPE arrayNames IS VARRAY(10) OF VARCHAR2(20);
    v1 arrayNames;
    CURSOR c_phonebook IS SELECT FIRSTNAME FROM PHONEBOOK;
BEGIN
    v1 := arrayNames(); 
    OPEN c_phonebook;
    LOOP
        FETCH c_phonebook INTO v_firstname;
        EXIT WHEN c_phonebook%NOTFOUND;
        v1.EXTEND();
        v1(v1.COUNT) := v_firstname;
    END LOOP;
    CLOSE c_phonebook;
END;
/

我假设这是一个练习;否则你可以使用批量收集到集合中,并且不需要显式游标:

DECLARE
    TYPE arrayNames IS VARRAY(10) OF VARCHAR2(20);
    v1 arrayNames;
BEGIN
    SELECT FIRSTNAME
    BULK COLLECT INTO v1
    FROM PHONEBOOK;
END;
/

(您可以向查询添加一个 rownum 检查以确保它不会尝试获取数组可以处理的更多行,但如果它曾经发生错误可能更合适发生了。)