Using a collection as parameter for a stored procedure
Sometimes you want to select rows where a value is in a specific collection. Here’s an example that show how you can select all the rows in the TEST table with an id of 1, 2 or 3. First we create an SQL type to contain a list of numbers:
CREATE TYPE LIST_NUMBER AS TABLE OF NUMBER(10); /
Next thing to do is add a custom type and function header to the package specification:
PACKAGE TIMVW.TESTPACKAGE AS TYPE CRSR_REF IS REF CURSOR; TYPE ARR_IDS IS TABLE OF TEST.TEST_ID%Type INDEX BY BINARY_INTEGER; PROCEDURE GET_TESTS ( P_IDS IN ARR_IDS, P_CURSOR OUT CRSR_REF ); END;
And offcourse we have to implement the function in the body:
PROCEDURE GET_TESTS
(
P_IDS IN ARR_IDS,
P_CURSOR OUT CRSR_REF
)
AS
V_IDS LIST_NUMBER := LIST_NUMBER();
BEGIN
V_IDS.EXTEND(P_IDS.COUNT);
FOR i IN P_IDS.FIRST .. P_IDS.LAST LOOP
V_IDS(i) := P_IDS(i);
END LOOP;
OPEN P_CURSOR FOR
SELECT
TEST.TEST_ID,
TEST.NAME,
TEST.TYPE_CODE
FROM
TEST
WHERE
TEST_ID IN (SELECT * FROM TABLE(V_IDS))
ORDER BY
TEST.TEST_ID ASC;
END;
Now that we have done all this we can consume the function from our client code:
using (OracleConnection conn = new OracleConnection("User Id=u;password=p;Data Source=ORCL"))
{
conn.Open();
OracleCommand command = conn.CreateCommand();
command.CommandType = CommandType.StoredProcedure;
command.CommandText = "TIMVW.TESTPACKAGE.GET_TESTS";
command.Parameters.Add("P_IDS", OracleDbType.Int32, new int[] { 1, 2, 3 }, ParameterDirection.Input);
command.Parameters["P_IDS"].CollectionType = OracleCollectionType.PLSQLAssociativeArray;
command.Parameters.Add("P_CURSOR", OracleDbType.RefCursor, ParameterDirection.Output);
OracleDataReader reader = command.ExecuteReader();
while (reader.Read())
{
Console.WriteLine("test id: " + reader.GetDecimal(0));
}
Console.Write("{0}Press any key to continue...", Environment.NewLine);
Console.ReadKey();
}
With PHP it’s as easy as:
$connection = oci_connect('u', 'p', 'ORCL'); $query = "BEGIN TIMVW.TESTPACKAGE.GET_TESTS(:P_IDS,
_CURSOR); END;";
$handler = oci_parse($connection, $query);
$ids = array(1, 2, 3);
$cursor = oci_new_cursor($connection);
oci_bind_array_by_name($handler, ":P_IDS", $ids, count($ids), -1, SQLT_NUM);
oci_bind_by_name($handler, ":P_CURSOR", $cursor, -1, OCI_B_CURSOR);
oci_execute($handler);
oci_execute($cursor);
while ($row = oci_fetch_assoc($cursor))
{
print $row['TEST_ID'] . "\r\n";
}
oci_close($connection);
?>April 8th, 2007 at 12:43
Hi,
Did you use ODP.Net for Oracle, for achieving this concept. Because System.Data.OracleClient (.Net Native) doesnt have OracleCollectionType class. Please let me know the details. Thanks.
October 15th, 2008 at 15:52
Yes, i have used ODP.NET for the implementation.
October 16th, 2008 at 08:01
[...] Da Sysan, I believe that this willd o what you want with MS’s Oracle data provider: http://www.timvw.be/using-a-collecti…red-procedure/ As for doing it in Java, you might get a response here, but you might want to repost this question [...]
January 18th, 2009 at 18:02