#plsql #oracle11g #nested-table
#plsql #oracle11g #вложенная таблица
Вопрос:
Я создал вложенную таблицу следующим образом:
CREATE OR REPLACE TYPE EMP_NO_NAME
AS OBJECT
(
EMPNO NUMBER(4),
ENAME VARCHAR2(20),
JOB VARCHAR2(20),
MGR NUMBER(5),
HIREDATE DATE,
SAL NUMBER(7,2)
);
CREATE OR REPLACE TYPE EMP_TABLE IS TABLE OF EMP_NO_NAME;
-----------------------
CREATE TABLE NESTED_EMP
(
DEPTNO NUMBER(2) ,
EMPLOYEE EMP_TABLE
)
NESTED TABLE EMPLOYEE STORE AS NESTED_EMPLOYEE;
INSERT INTO NESTED_EMP (DEPTNO,EMPLOYEE)
VALUES (10,EMP_TABLE(EMP_NO_NAME(7839,'KING','PRESIDENT',NULL,'17-NOV-81',5000),
EMP_NO_NAME(7782,'CLARK','MANAGER',7839,'09-JUN-81',2450),
EMP_NO_NAME(7934,'MILLER','CLERK',7782,'23-JAN-82',1300)
)
);
INSERT INTO NESTED_EMP (DEPTNO,EMPLOYEE)
VALUES (20,EMP_TABLE(EMP_NO_NAME(7566,'JONES','MANAGER',7839,'02-APR-81',2975),
EMP_NO_NAME(7902,'FORD','ANALYST',7566,'03-DEC-81',3000),
EMP_NO_NAME(7369,'SMITH','CLERK',7902,'17-DEC-80',800),
EMP_NO_NAME(7788,'SCOTT','ANALYST',7566,'09-DEC-82',3000),
EMP_NO_NAME(7876,'ADAMS','CLERK',7788,'12-JAN-83',1100)
)
);
INSERT INTO NESTED_EMP (DEPTNO,EMPLOYEE)
VALUES (20,EMP_TABLE(EMP_NO_NAME(7698,'BLAKE','MANAGER',7839,'01-MAY-81',2850),
EMP_NO_NAME(7654,'MARTIN','SALESMAN',7698,'28-SEP-81',1250),
EMP_NO_NAME(7499,'ALLEN','SALESMAN',7698,'20-FEB-81',1600),
EMP_NO_NAME(7844,'TURNER','SALESMAN',7698,'08-SEP-81',1500),
EMP_NO_NAME(7900,'JAMES','CLERK',7698,'03-DEC-81',950),
EMP_NO_NAME(7521,'WARD','SALESMAN',7698,'22-FEB-81',1250)
)
);
Теперь я получаю значение вложенной таблицы в plsql:
DECLARE
CURSOR EMPLOYEE IS
select p.* from NESTED_EMP p1 ,table(p1.employee) p;
V_EMP EMP_TABLE;
BEGIN
FOR V_EMP IN EMPLOYEE
LOOP
EXIT WHEN EMPLOYEE%NOTFOUND;
END LOOP;
FOR MYINDEX IN V_EMP.FIRST..V_EMP.LAST
LOOP
DBMS_OUTPUT.PUT_LINE(V_EMP(MYINDEX).ENAME);
END LOOP;
END;
/
END;
Сообщение об ошибке:
ORA-06531: ссылка на неинициализированную коллекцию ORA-06512: в строке 10 06531. 00000 — «Ссылка на неинициализированную коллекцию»
* Причина: была сделана ссылка на элемент или функцию-член вложенной таблицы или varray (где требуется инициализированная коллекция) без инициализации коллекции.
* Действие: Инициализируйте коллекцию с помощью соответствующего конструктора или назначения целого объекта.
Как получить значение вложенной таблицы в таблице plsql?
Комментарии:
1. Это был красиво сформулированный вопрос. Предоставление DDL для полного воссоздания сценария очень полезно.
Ответ №1:
Проблема с вашим кодом заключается в том, что V_EMP
на самом деле он не имеет типа EMP_TABLE
. Скорее, это EMPLOYEE.ROWTYPE
. Когда вы инициализируете курсор для цикла, переменной автоматически присваивается соответствующее значение ROWTYPE
, переопределяя все предыдущие объявления.
Хорошей новостью является то, что, поскольку вы уже ссылались на вложенную таблицу в запросе, вам не нужно делать это в цикле (он уже разнесен). Ваш PL / SQL может быть значительно упрощен:
DECLARE
CURSOR employee IS
SELECT p.*
FROM nested_emp p1 CROSS JOIN TABLE (p1.employee) p;
BEGIN
FOR v_emp IN employee LOOP
DBMS_OUTPUT.put_line (v_emp.ename);
END LOOP;
END;
/
Вы заметите, что EXIT WHEN
также был удален. Курсор для цикла автоматически завершается после последней записи.
Альтернативой было бы не разбивать вложенную таблицу в запросе. Тогда вам понадобятся два цикла:
DECLARE
CURSOR employee IS
SELECT p.*
FROM nested_emp p;
BEGIN
FOR v_emp IN employee LOOP
for i in v_emp.employee.first..v_emp.employee.last loop
DBMS_OUTPUT.put_line (v_emp.employee(i).ename);
end loop;
END LOOP;
END;
/
Комментарии:
1. есть ли другой способ получить значение вложенной таблицы в блоке plsql