问题
How can I return a set of data from PL/SQL?
I have a stored procedure that needs to run a select statement and returns the result back to the calling (Java) program.
The select statement comprises of a few joins from multiple tables, so I am not sure how to define this type in the stored procedure definition or body.
I was thinking maybe this can be done as following, but SQL Developer is giving me errors:
CREATE OR REPLACE PACKAGE my_package
AS
TYPE a_collection_records IS RECORD (
NUMBER FIRST_COL,
VARCHAR2 SECOND_COL -- a few others
);
-- Procedure API that uses a_collection_records type
END;
CREATE OR REPLACE PROCEDURE sample_procedure(
p_some_select_sql_result OUT my_package.a_collection_records
)
AS
BEGIN
-- Populate p_some_select_sql_result with some select data
END;
回答1:
Unless you are particularly set on using a collection, it would be simpler to use a ref cursor:
CREATE OR REPLACE PROCEDURE sample_procedure (
p_some_select_sql_result OUT SYS_REFCURSOR
)
AS
BEGIN
OPEN p_some_select_sql_result FOR
SELECT ...
FROM ...
JOIN ...
... etc.;
END;
/
From JDBC you can then do something like:
cStmt = conn.prepareCall('{ call sample_procedure(?) }');
cStmt.registerOutParameter(1, oracle.jdbc.OracleTypes.CURSOR);
cStmt.execute();
rSet = cStmt.getCursor(1);
and you can then iterate over the result set as you would with any other.
You could also use a function instead:
CREATE OR REPLACE FUNCTION sample_function RETURN SYS_REFCURSOR
AS
l_some_select_sql_result
BEGIN
OPEN l_some_select_sql_result FOR
SELECT ...
FROM ...
JOIN ...
... etc.;
RETURN l_some_select_sql_result;
END;
/
and
cStmt = conn.prepareCall('{ ?=call sample_function }');
cStmt.registerOutParameter(1, oracle.jdbc.OracleTypes.CURSOR);
cStmt.execute();
rSet = cStmt.getCursor(1);
Obviously you need to handle any other parameters you're passing to your real procedure/function.
回答2:
Your type definition is a little bit out of order. You have the type definition before the name of the item.
TYPE a_collection_records IS RECORD (
NUMBER FIRST_COL,
VARCHAR2 SECOND_COL -- a few others
);
It should be
TYPE a_collection_records IS RECORD (
FIRST_COL NUMBER,
SECOND_COL VARCHAR2 -- a few others
);
The name of the column comes before the column's datatype. I hope this is what you are looking for. You could always do a refcursor, but if you want names that are not the actual column names on the tables you are selecting from then you will still what a record type.
To be able to create it as a custom set just declare after the close of the RECORD
definition the following line of code
TYPE collection_list IS TABLE a_collection_records;
Complete example:
TYPE a_collection_records IS RECORD (
FIRST_COL NUMBER,
SECOND_COL VARCHAR2 -- a few others
);
TYPE collection_list IS TABLE OF a_collection_records;
That will give you a custom (and column masked) set of data.
来源:https://stackoverflow.com/questions/51252292/how-to-return-a-custom-set-in-pl-sql-stored-procedure