如何在具有多个连接的 Pl/SQL 中编写对象类型作为输出参数的存储过程
How to write store procedure with object type as out parameter in Pl/SQL with multiple joins
我正在尝试使用以下示例用例和表编写存储过程,
员工<br>
Emp_id Emp_Name
1 乔恩
2马克
3 结婚
部门<br>
Emp_Id Dept_Id
1个
2乙
3C
1乙
二维
Assets
Emp_Id Asset_Name
1 AA
1 BB
2 CC
2 DD
4 EE
4 FF
关系
可以将一名员工添加到多个部门。
例如 Emp 1 添加到 A 和 B 部门。
一名员工可以拥有多项资产
例如 Emp 1 欠资产 AA 和 BB。
员工和资产之间没有外键约束。
所以 Assets 可以有 EmpId,这在 Employee Table 中是不可用的。
例如 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]
所以想为this.Please写一个存储过程建议解决这个问题。
这可以通过多个游标或对象类型输出变量来实现吗?
存储过程我试过如下,
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;
提前致谢
最好创建包定义和包体。您的包裹定义如下所示:
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;
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 |
我正在尝试使用以下示例用例和表编写存储过程,
员工<br>
Emp_id Emp_Name
1 乔恩
2马克
3 结婚
部门<br>
Emp_Id Dept_Id
1个
2乙
3C
1乙
二维
Assets
Emp_Id Asset_Name
1 AA
1 BB
2 CC
2 DD
4 EE
4 FF
关系
可以将一名员工添加到多个部门。 例如 Emp 1 添加到 A 和 B 部门。
一名员工可以拥有多项资产 例如 Emp 1 欠资产 AA 和 BB。
员工和资产之间没有外键约束。 所以 Assets 可以有 EmpId,这在 Employee Table 中是不可用的。 例如 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]
所以想为this.Please写一个存储过程建议解决这个问题。 这可以通过多个游标或对象类型输出变量来实现吗?
存储过程我试过如下,
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;
提前致谢
最好创建包定义和包体。您的包裹定义如下所示:
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;
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 |