Domanda

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.

È stato utile?

Soluzione

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.

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top