Much like this question, I am looking to return a resultset from function and work with this resultset just like with an ordinary table, but with the extra twist that I want to do this from within a procedure (using Oracle versions >= 11).
My basic intent is to allow the results of a dynamic query be used as a starting point for a very complex static SQL statement.
For calls directly from a SQL*PLUS prompt, multiple solutions exist, but they all seem to fail when run in a procedure. For example, using 'method4':
SQL> WITH q AS (SELECT * FROM TABLE(method4.query('select id, pid from
2 my_table where rownum < 100')))
3 SELECT * FROM q where rownum <4;
ID PID
--------------- ----------
72 499
11 89
13 23
3 rows selected.
SQL> CREATE OR REPLACE PROCEDURE test_x (
2 p_sql IN VARCHAR2,
3 p_results OUT SYS_REFCURSOR
4 ) IS
5 BEGIN
6 open p_results for
7 WITH q AS (SELECT * FROM TABLE(method4.query(p_sql)))
8 SELECT * FROM q where rownum <4; -- this is where the complex logic would go
9 END test_x;
10 /
Warning: Procedure created with compilation errors.
SQL> show errors
Errors for PROCEDURE TEST_X:
LINE/COL ERROR
-------- -----------------------------------------------------------------
7/4 PL/SQL: SQL Statement ignored
7/29 PL/SQL: ORA-22905: cannot access rows from a non-nested table
item
SQL>
In my real application, the query in the procedure will be quite long and complex. I want to avoid generating dynamic SQL for each call. (That is my current 'fall-back' solution.)
Is there a way to leverage 'ANYDATASET table functions' from within stored procedures?
Update: I have been informed that receiving pipelined content in a PL/SQL context is not possible. I believe that only leaves me with a non-pipelined approach - which I believe has the same problem...
Given the following non-pipelined analog of the initial SQL:
SQL> CREATE OR REPLACE FUNCTION myQuery (
2 p_1 IN VARCHAR2
3 ) RETURN ANYDATASET AS p_result ANYDATASET;
4 BEGIN
5 EXECUTE IMMEDIATE p_1 INTO p_result;
6 RETURN(p_result);
7 END myQuery;
8 /
Function created.
SQL> CREATE OR REPLACE PROCEDURE test_x2 (
2 p_sql IN VARCHAR2,
3 p_results OUT SYS_REFCURSOR
4 ) IS
5 myset anydataset;
6 BEGIN
7 myset := method4.query(p_sql);
8 open p_results for
9 WITH q AS (SELECT * FROM TABLE(myset))
10 SELECT * FROM q where rownum <4; -- this is where the complex logic would go
11 END test_x2;
12 /
Warning: Procedure created with compilation errors.
SQL> show errors
Errors for PROCEDURE TEST_X2:
LINE/COL ERROR
-------- -----------------------------------------------------------------
9/7 PL/SQL: SQL Statement ignored
9/32 PL/SQL: ORA-22905: cannot access rows from a non-nested table
item
106/13 PLS-00653: aggregate/table functions are not allowed in PL/SQL
scope
It appears that the use of table functions is not allowed in PL/SQL - independent of pipelining or not.
If so, are there any other ways to take take a dynamic query for which the resulting schema can be anything, and feed it into a subsequent static query as a 'with' input, all within a PL/SQL procedure?