Как написать процедуру хранения с типом объекта как выходной параметр в Pl / SQL с несколькими объединениями - PullRequest
0 голосов
/ 10 мая 2018

Я пытаюсь написать процедуру хранения с приведенным ниже примером использования и таблицами,

Employee<br> Emp_id Emp_Name 1 Jhon 2 Mark 3 Marry

Department<br> Emp_Id Dept_Id 1 A 2 B 3 C 1 B 2 D

Assets Emp_Id Asset_Name 1 AA 1 BB 2 CC 2 DD 4 EE 4 FF

Отношения

Один сотрудник может быть добавлен в несколько отделов. например, Emp 1 добавлен в отделы A и B.

Один сотрудник может иметь более одного актива например, Эмпел 1, имеющий активы AA и BB.

Нет ограничений по внешнему ключу между сотрудником и активами. Таким образом, у активов может быть значение EmpId, которого нет в таблице сотрудников. например, Emp 4

Желаемый выход

EmployeeInfo Emd_Id Emp_Name Array of Dept_Id[] Array of Assets[]

Желаемый результат для сотрудника Id 1

Emd_Id :1 Emp_Name :Jhon Array of Dept_Id[] :[A,B] Array of Assets[] :[AA,BB]

Желаемый результат для сотрудника Id 4

Emd_Id :4 Emp_Name :null -- As no entry in Employee table. Array of Dept_Id[] :null Array of Assets[] :[EE,FF]

Итак, напишите процедуру хранения для этого. Пожалуйста, предложите решение для этого. Или это может быть достигнуто с помощью нескольких курсоров или переменных типа объекта?

Хранимая процедура, которую я пробовал, как показано ниже,

CREATE OR REPLACE PROCEDURE PRC_TEST( employeeInfo OUT SYS_REFCURSOR) IS BEGIN OPEN employeeInfo FOR SELECT e.EMP_ID ,e.EMP_NAME, d.DEPT_ID, a.ASSET_NAME FROM EMPLOYEE e, DEPARTMENT d, ASSETS a WHERE e.EMP_ID = d.EMP_ID AND e.EMP_ID = a.EMP_ID; END; Заранее спасибо

Ответы [ 2 ]

0 голосов
/ 10 мая 2018

SQL Fiddle

Настройка схемы Oracle 11g R2 :

CREATE TABLE Employee ( Emp_id, Emp_Name ) AS
SELECT 1, 'Jhon' FROM DUAL UNION ALL
SELECT 2, 'Mark' FROM DUAL UNION ALL
SELECT 3, 'Marry' FROM DUAL
/

CREATE TABLE Department ( Emp_Id, Dept_Id ) AS
SELECT 1, 'A' FROM DUAL UNION ALL
SELECT 2, 'B' FROM DUAL UNION ALL
SELECT 3, 'C' FROM DUAL UNION ALL
SELECT 1, 'B' FROM DUAL UNION ALL
SELECT 2, 'D' FROM DUAL
/

CREATE TABLE Assets ( Emp_Id, Asset_Name ) AS
SELECT 1, 'AA' FROM DUAL UNION ALL
SELECT 1, 'BB' FROM DUAL UNION ALL
SELECT 2, 'CC' FROM DUAL UNION ALL
SELECT 2, 'DD' FROM DUAL UNION ALL
SELECT 4, 'EE' FROM DUAL UNION ALL
SELECT 4, 'FF' FROM DUAL
/

CREATE TYPE StringLIst IS TABLE OF VARCHAR2(20)
/

CREATE TYPE Emp_Dept_Assets_Obj AS OBJECT(
  Emp_id   INTEGER,
  Emp_Name VARCHAR2(50),
  Depts    StringList,
  Assets   StringList
)
/

CREATE FUNCTION get_Details(
  i_emp_id  IN  Employee.EMP_ID%TYPE
) RETURN Emp_Dept_Assets_Obj
IS
  o_details Emp_Dept_Assets_Obj;
BEGIN
  o_details := Emp_Dept_Assets_Obj( i_emp_id, NULL, NULL, NULL );

  BEGIN
    SELECT Emp_Name
    INTO   o_details.Emp_Name
    FROM   Employee
    WHERE  emp_id = i_emp_id;
  EXCEPTION
    WHEN NO_DATA_FOUND THEN
      NULL;
  END;

  SELECT dept_id
  BULK COLLECT INTO o_details.Depts
  FROM   Department
  WHERE  emp_id = i_emp_id;

  SELECT asset_name
  BULK COLLECT INTO o_details.Assets
  FROM   Assets
  WHERE  emp_id = i_emp_id;

  RETURN o_details;
END;
/

Запрос 1 :

SELECT d.details.emp_id,
       d.details.emp_name,
       d.details.depts,
       d.details.assets
FROM   (
  SELECT get_Details( LEVEL ) AS details
  FROM   DUAL
  CONNECT BY LEVEL <= 4
) d

Результаты

| DETAILS.EMP_ID | DETAILS.EMP_NAME | DETAILS.DEPTS | DETAILS.ASSETS |
|----------------|------------------|---------------|----------------|
|              1 |             Jhon |           A,B |          AA,BB |
|              2 |             Mark |           B,D |          CC,DD |
|              3 |            Marry |             C |                |
|              4 |           (null) |               |          EE,FF |
0 голосов
/ 10 мая 2018

Лучше всего создать определение пакета и тело. Ваше определение пакета будет примерно таким:

CREATE OR REPLACE PACKAGE EmployeeInfo AS

TYPE departament_type IS TABLE OF VARCHAR2(100);
TYPE assets_type      IS TABLE OF VARCHAR2(100);

PROCEDURE get_employee_info ( Emp_Id_col      IN OUT NUMBER
                             ,Emp_Name_col       OUT VARCHAR2
                             ,departament_tbl    OUT DEPARTAMENT_TYPE
                             ,assets_tbl         OUT ASSETS_TYPE);

END EmployeeInfo;

Тогда тело вашего пакета будет соответствовать вашему определению, и именно здесь будет реализована процедура:

CREATE OR REPLACE PACKAGE BODY EmployeeInfo AS

PROCEDURE get_employee_info ( Emp_Id_col      IN OUT NUMBER
                             ,Emp_Name_col       OUT VARCHAR2
                             ,departament_tbl    OUT DEPARTAMENT_TYPE
                             ,assets_tbl         OUT ASSETS_TYPE)
IS 
BEGIN

BEGIN
  SELECT Emp_Name
  INTO   Emp_Name_col
  FROM   Employee
  WHERE  Emp_Id = Emp_Id_col;
EXCEPTION
  WHEN NO_DATA_FOUND THEN  
    RETURN;
END;  

departament_tbl := DEPARTAMENT_TYPE();

FOR dep_rec IN (SELECT *
                FROM   Department
                WHERE  Emp_id = Emp_Id_col) LOOP 
  departament_tbl.extend;
  departament_tbl(departament_tbl.COUNT) := dep_rec.Dep_Id;
END LOOP;

assets_tbl := ASSETS_TYPE();

FOR asset_rec IN (SELECT *
                  FROM   Assets
                  WHERE  Emp_Id = Emp_Id_col) LOOP 
  assets_tbl.extend;
  assets_tbl(assets_tbl.COUNT) := asset_rec.Asset_Name;
END LOOP;

END get_employee_info;

END EmployeeInfo;

Теперь здесь есть очень простой тестовый скрипт для вашей хранимой процедуры:

DECLARE
  Emp_Id_col            NUMBER(10);
  Emp_Name_col          Employee.Emp_Name%TYPE;
  departament_tbl       EMPLOYEEINFO.DEPARTAMENT_TYPE;
  assets_tbl            EMPLOYEEINFO.ASSETS_TYPE;
BEGIN
  Emp_Id_col := 1;
  EMPLOYEEINFO.GET_EMPLOYEE_INFO(Emp_Id_col
                                ,Emp_Name_col
                                ,departament_tbl
                                ,assets_tbl);

  DBMS_OUTPUT.PUT_LINE(Emp_Name_col          || ' - ' ||
                       departament_tbl.COUNT || ' - ' || 
                       assets_tbl.COUNT);

END;
...