How to Return a Custom Set in PL/SQL Stored Procedure

ⅰ亾dé卋堺 提交于 2020-01-16 07:31:29

问题


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

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!