I\'m trying to create a stored function in oracle that returns multiple rows.
My question is very similar to this one except that I want to fetch a select *
If you are using PHP and you want to access a oracle stored function. You can make use of something like this
//Your connection details
$conn = oci_connect($username, $password, '(DESCRIPTION = (ADDRESS = (PROTOCOL = TCP)(HOST = 127.0.0.1)(PORT = 1521))(CONNECT_DATA = (SERVER = DEDICATED) (SERVICE_NAME = XE)))' );
/* Your query string; you can use oci_bind_by_name to bind parameters or just pass the variable in it*/
$query = "begin :cur := functionName('".$param1."','".$param2."','".$param3."'); end;";
$stid = oci_parse($conn, $query);
$OUTPUT_CUR = oci_new_cursor($conn);
oci_bind_by_name($stid, ':cur', $OUTPUT_CUR, -1, OCI_B_CURSOR);
oci_execute($stid);
oci_execute($OUTPUT_CUR);
oci_fetch_all($OUTPUT_CUR, $res);
// To get your result
var_dump($res);
I hope this helps.
with SQL types you cant do %ROWTYPE, you'd have to type each column to match the table*.
*sys.anydataset aside. but going down that route is a lot more complex coding.
e.g. if your table was
create table foo (id number, cola varchar2(1));
then
create type email_queue_type is object (id number, cola varchar2(1));
/
create type t_email_queue_type as table of email_queue_type;
/
and use that table email_queue_type_tab as the output from your function.
but i'd recommend a pipelined function, as your current code isn't scalable.
eg:
SQL> create table foo (id number, cola varchar2(1));
Table created.
SQL>
SQL> create type email_queue_type is object (id number, cola varchar2(1));
2 /
Type created.
SQL> create type t_email_queue_type as table of email_queue_type;
2 /
Type created.
SQL> insert into foo select rownum, 'a' from dual connect by level <= 10;
10 rows created.
SQL>
SQL> create or replace PACKAGE email_queue AS
2
3
4 FUNCTION lock_and_get return t_email_queue_type pipelined;
5
6 END email_queue;
7 /
Package created.
SQL> create or replace PACKAGE BODY email_queue AS
2
3 FUNCTION lock_and_get RETURN t_email_queue_type pipelined AS
4 queue_obj t_email_queue_type;
5
6 BEGIN
7
8 for r_row in (select * from foo)
9 loop
10 pipe row(email_queue_type(r_row.id, r_row.cola));
11 end loop;
12
13 END lock_and_get;
14
15 END email_queue;
16 /
Package body created.
SQL> select * from table(email_queue.lock_and_get());
ID C
---------- -
1 a
2 a
3 a
4 a
5 a
6 a
7 a
8 a
9 a
10 a
10 rows selected.
SQL>
If you aren't particularly keen on having the SQL type, you could do this with a sys_refcursor
instead:
create or replace package email_queue as
function lock_and_get return sys_refcursor;
end email_queue;
/
create or replace package body email_queue as
function lock_and_get return sys_refcursor AS
c sys_refcursor;
lockid varchar2(100) := 'alf';
begin
open c for
select * from t_email_queue
where lockedby = lockid;
return c;
end lock_and_get;
end email_queue;
/
From SQL*Plus you could call it something like:
var cur refcursor;
exec :cur := email_queue.lock_and_get;
print cur
and as exec
is shorthand for a simple anonymous block you can call if from other PL/SQL objects too. What you can't do, though, is:
select * from table(email_queue.lock_and_get);
I'm not familiar with calling functions from PHP, but from Java you can use this directly as the return from a callable statement, so you don't need the select * from table()
construct at all. I have no idea if you can execute an anonymous block in a PHP call, something like begin $cur = email_queue.lock_and_get; end;
, and have $cur
as your result set that you can then iterate through?
I realise this isn't a complete answer as the PHP side is way too vague, but might give you some ideas.