Заполнение вложенных таблиц с помощью CAST / MULTISET - PullRequest
0 голосов
/ 31 октября 2019

Получение ошибки при заполнении вложенных коллекций с использованием CAST / MULTISET.

Создание объекта

--Employee Object 
CREATE TYPE emp_o AS OBJECT (
    employee_id     NUMBER,
    employee_name   VARCHAR2(100),
    salary          NUMBER
);

--Employee table

CREATE TYPE emp_ot IS
    TABLE OF emp_o;
--Department object

CREATE TYPE deps_o AS OBJECT (
    department_id     NUMBER,
    department_name   VARCHAR2(100),
    emp_tab           emp_ot
);
--department table

CREATE TYPE deps_t IS
    TABLE OF deps_o;

Ниже приведен мой запрос, который я использую: в основном попытка заполнениятаблица deps_t за один раз.

DECLARE 
  l_message DEPS_T := DEPS_T(); --Initialize 
BEGIN 
  SELECT CAST ( MULTISET (
                SELECT d.department_id, 
                       d.department_name, 
                       CAST(MULTISET(
                              SELECT e.employee_id, 
                                     e.first_name ||' ' ||e.last_name,
                                     e.salary 
                              FROM   hr.employees e 
                              WHERE  e.department_id = d.department_id ) AS EMP_OT) 
                ) AS deps_t)
  INTO   l_message 
  FROM   hr.departments d; 

END;

Ошибка, которую я получаю:

ORA-06550: line 13, column 17:
PL/SQL: ORA-00923: FROM keyword not found where expected 

Ответы [ 3 ]

2 голосов
/ 31 октября 2019

Спасибо @GMB Ниже работает запрос

DECLARE 
  l_message DEPS_T := DEPS_T(); --Initialize 
BEGIN 
  SELECT CAST ( MULTISET (
                SELECT d.department_id, 
                       d.department_name, 
                       (CAST(MULTISET(
                              SELECT e.employee_id, 
                                     e.first_name ||' ' ||e.last_name,
                                     e.salary 
                              FROM   hr.employees e 
                              WHERE  e.department_id = d.department_id ) AS EMP_OT) )
                FROM hr.departments d) AS deps_t)
  INTO   l_message 
  FROM DUAL;


END;
1 голос
/ 31 октября 2019

Хотя приведенный выше код работает, как и ожидалось, как разработчик, мне было немного трудно его понять. А как насчет упрощения приведенного выше кода, если убрать встроенные запросы и операторы MULTISET & CAST? Посмотрите как:

DECLARE 
  l_message DEPS_T;
BEGIN 
  SELECT  deps_o(
              d.deptno
             ,d.dname
              --Writing type of table does implicit casting here
             ,EMP_OT(emp_o (
                                    e.empno,
                                    e.ename || ' ' || 'last_name',
                                    e.sal
                                  )                                                                                       
                             ))           
  BULK COLLECT INTO l_message 
  FROM   dept d
  JOIN emp e
  ON e.deptno = d.deptno;      

   for i in 1..l_message.count
   loop
     dbms_output.put_line(l_message(i).department_id ||' '||l_message(i).department_name||' '||l_message(i).emp_tab(1).employee_id);
   end loop;

END;
/

Вывод:

SQL> /
10 ACCOUNTING 7782
10 ACCOUNTING 7839
10 ACCOUNTING 7934
20 RESEARCH 7566
20 RESEARCH 7902
20 RESEARCH 7876
20 RESEARCH 7369
20 RESEARCH 7788
30 SALES 7521
30 SALES 7844
30 SALES 7499
30 SALES 7900
30 SALES 7698
30 SALES 7654

PL/SQL procedure successfully completed.
1 голос
/ 31 октября 2019

Вам не нужно инициализировать коллекцию, и вы можете избавиться от внешнего CAST / MULTISET с помощью BULK COLLECT INTO. Вы также можете явно создавать объекты deps_o и emp_o (создание emp_o необязательно, поскольку MULTISET будет обрабатывать его, но это необходимо для deps_o, так как BULK COLLECT INTO ожидает, что для каждой переменной будет введен отдельный столбецэто накапливается):

DECLARE 
  l_message DEPS_T;
BEGIN 
  SELECT deps_o(
           department_id,
           department_name,
           CAST(
             MULTISET(
               SELECT emp_o(
                        employee_id,
                        first_name || ' ' || last_name,
                        salary
                      )
               FROM   employees e
               WHERE  e.department_id = d.department_id
             ) AS emp_ot
           )
         )
  BULK COLLECT INTO l_message 
  FROM   departments d; 
END;
/
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...