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