Извлечение данных таблицы с помощью курсора в Varray в базе данных Oracle

У меня есть таблица с именем PhoneBook с такими атрибутами: ID, FirstName, LastName. и у него есть 5 записей. Я хочу создать VARRAY и извлечь все 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: нижний индекс за пределами предела ORA-06512: в строке 14 06532. 00000 - "нижний индекс за пределами предела" * Причина: нижний индекс был больше, чем предел для varray или не был положительным для таблицы varray или nested. * Действие: Проверьте логику программы и при необходимости увеличьте предел варриа.

Пожалуйста, помогите мне решить эту проблему. благодарю вас

1 ответ

Решение

Вам нужно увеличить размер массива, создавая пустой элемент, который вы затем можете заполнять каждый раз, когда хотите добавить элемент:

...
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 сразу после FETCH, поэтому вы не пытаетесь обработать последнюю строку из курсора дважды.

Вам на самом деле не нужно 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 проверьте запрос, чтобы убедиться, что он не пытается получить больше строк, которые может обработать массив, но для этого может быть более уместно выдавать ошибку, если это произойдет.)

Другие вопросы по тегам