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);
?>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.
Yes, i have used ODP.NET for the implementation.
Sorry, im a newbie in Oracle with .Net programming.
If my type was created like this:
CREATE OR REPLACE TYPE TableNumberType as table of number;
/
And my procedure is like this:
CREATE OR REPLACE PROCEDURE Z_TEST(pn_data TableNumberType) IS
BEGIN
FORALL i IN 1 .. pn_data.COUNT
INSERT INTO Z_TEST_TABLE VALUES (pn_data(i));
END;
/
I must still create a Package to implement this? I am getting “wrong number or types of args” when i use:
OracleParameter prm = new OracleParameter(“parname”, OracleDbType.Decimal);
and
“invalid parameter binding” when i use:
OracleParameter prm = new OracleParameter(“parname”, OracleDbType.Array);
I am losing my mind on this one