2

I am looking for a way to return an array of values from a procedure in PL/SQL.

The procedure has some input parameter. Based on these inputs, an select query will be created and executed. On the result of this query, some more validation and calculation will be executed. The result of these checks and calculations should be saved in a new array or table array that will then be returned from the procedure. This procedure will be called several times from another PL/SQL script, with different parameters in order to get different values and to different checks on these values.

Is there a way to return an array from a procedure? I am looking for a solution that avoids unnecessary copying of data and is as fast as possible.

I have read about temporary tables, PL/SQL tables, cursors and so on, but I am not sure, which is these is the best approach.

3
  • 2
    Showing your work will be helpful. Commented May 13, 2014 at 15:16
  • 3
    There is no such thing as one best approach for everything. It depends on what your use case is. Commented May 13, 2014 at 15:23
  • I do not yet have any source code that could be discussed. I just wanted to know which way to go. So if somebody can name concepts of Oracle PL/SQL that may lead to a solution, I will be happy. Commented May 13, 2014 at 15:39

1 Answer 1

4

Can a function return an array (procedures have OUT parameters, functions return things)? Sure

CREATE OR REPLACE PACKAGE some_pkg
AS
  TYPE my_assoc_array_typ IS TABLE OF emp%rowtype INDEX BY PLS_INTEGER;

  FUNCTION return_array( p_deptno IN emp.deptno%type )
    RETURN my_assoc_array_typ;
END;

CREATE OR REPLACE PACKAGE BODY some_pkg
AS
  FUNCTION return_array( p_deptno IN emp.deptno%type )
    RETURN my_assoc_array_typ
  IS
    l_emps my_assoc_array_typ;
  BEGIN
    SELECT *
      BULK COLLECT INTO l_emps
      FROM emp
     WHERE deptno = l_deptno;

    RETURN l_emps;
  END;
END;

Now, is that the most efficient approach? It might be, it might not be depending on your environment. If there was a single approach that was always more efficient than the alternatives, Oracle wouldn't bother implementing the alternatives.

Using associative arrays (or any PL/SQL collection type) means that your data is stored in the relatively expensive PGA memory on the server. If you have one session reading a few hundred rows into a collection, that's probably not a major concern. If, on the other hand, you have thousands of sessions simultaneously trying to work with collections that have multiple millions of rows, PL/SQL collections will almost certainly create a bottleneck on the database server where most of the server's RAM is now dedicated to supporting these collections. Of course, you can often work around these problems by fetching smaller numbers of rows into each collection and, presumably, allowing for subsequent calls to fetch subsequent sets of rows, but that means architecture changes.

In contrast, data stored in a temporary table, just like data stored in a permanent table, may be in the buffer cache or may be on disk at any point in time. That makes a temporary table more appropriate when you want to manage larger data volumes. But it comes at the cost of performance that you'll likely be doing at least some reads from and writes to physical disk and that your temporary table data will be competing with other data for space in the buffer cache.

A cursor does not store data, it's just a pointer to a program (a compiled SQL statement) that can be executed to fetch the next row of data you want.

Sign up to request clarification or add additional context in comments.

3 Comments

Thank you for your answer. It seems as if temporary tables will be the approach that fits to my needs. I will have very few sessions but these sessions have to handle a lot of data. I definitely want to avoid the cost of copying a lot of data in memory when the function returns, so using a temporary table sounds reasonable. I hope that this way, the code in the function and outside of the function access the same part of memory.
@user3633126 - I'm not sure what "copying a lot of data in memory" means to you. A PL/SQL collection does not need to be copied when passed from one PL/SQL block to another (assuming you specify NOCOPY in your parameter definitions). The data needs to be copied from the SQL engine to the PL/SQL engine, of course, to initially populate the collection. If you're certain that you need to materialize the data in the first place, a temporary table may be appropriate, but then the data likely won't all be in memory when you read it.
I was not aware that no copy of the data will created when returning from a function. I was just thinking of languages like C++ where passing a pointer to a function avoids creating a copy of a parameter on the stack. But if this is managed by PL/SQL, thats fine.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.