Refcusor as input to stored procedure - sql

Is it possible to pass refcursor as input variable to a stored procedure. Like:
PROCEDURE TESTPROCEDURE
(p_in IN SYS_REFCURSOR)
IS
BEGIN
--Stored Procedure logic--
END;
It would be really helpful if get some sort of example. Thanks

I have found the answer, refcursor can be passed as input to a stored procedure. E.g.
create or replace TEST_PROCEDURE
(
rc in sys_refcursor
)
as
data varchar2(10);
begin
loop
FETCH rc INTO data;
exit when rc%NOTFOUND;
DBMS_OUTPUT.put_line ('data =' ||data);
end loop;
end TEST_PROCEDURE

Related

Create stored procedure which accepts input as stored procedure and produce results dynamically

I want to implement this below requirements:
Sample procedure #1:
Procedure Proc1(Input1 VARCHAR2,
Input2 NUMBER,
Input3 VARCHAR2,
Output Sys_RefCursor)
IS
BEGIN
..................
..................
..................
END;
Sample procedure #2:
Procedure Proc2(Ipval1 VARCHAR2,
Ipval2 NUMBER,
Ipval3 VARCHAR3
Output Sys_RefCursor)
IS
Begin
..................
..................
..................
End;
Now the requirement is, I want to create a stored procedure which should accept the procedure name as input.
So according to the input procedure name, it should dynamically produce the result of it.
Procedure GenProc(InputProcedureName VARCHAR2,
InputListVal VARCHAR2,
OutputCur SYS_REFCURSOR)
IS
Begin
................Dynamic Code ............... To produce result set as per input procedurename
END;
Any idea how to write dynamic code to fulfill this requirement?
Let's say here:
InputProcedureName -- Can be Proc1 or Proc2 ,
InputListVal -- List of input given in comma separated value for the input procedurenames,
OutputCur -- Should produce output list dynamically as per the input procedurename
Something like this:
create or replace procedure Proc1 (
par1 varchar2,
par2 number,
par3 varchar2,
rc out sys_refcursor) is
begin
open rc for
select 'executing Proc1('||par1||','||par2||','||par3||')' result from dual;
end;
/
create or replace procedure execProc (
procname varchar2,
args sys.odciVarchar2List,
rc out sys_refcursor) is
begin
execute immediate 'begin '||procname||q'[(:s1, :n2, :s3, :rc); end;]'
using args(1), to_number (args(2)), args(3), out rc;
end;
/
The execution and outcomes:
set autoprint on
var rc refcursor
exec execProc ('Proc1', sys.odciVarchar2List ('abc', 123, 'def'), :rc)
RESULT
--------------------------------
executing Proc1(abc,123,def)
Disclaimer: This answer is meant for educational purposes only!!!

Anonymous PL/SQL Block to call a procedure with collection

I need to test a package procedure which accepts a PL/SQL table and returns SYS_REFCURSOR.
What I am looking for is Anonymous PL/SQL block which does the following :
populates PL/SQL table and pass to procedure
The relevant code is below:
create or replace type rec_typ as object
(
fname varchar2(10),
lname varchar2(10)
)
/
create or replace type rec_arr as table of rec_typ
/
create or replace package get_emp_pkg
as
procedure get_emp
(
l_rec rec_arr,
p_out out sys_refcursor
);
end;
/
create or replace package body get_emp_pkg
as
procedure get_emp
(
l_rec rec_arr,
p_out out sys_refcursor
)
as
l_out rec_arr;
begin
open p_out for select * from table ( l_out );
end;
end;
/
You need to declare and populate a table collection, and declare a cursor variable; and then pass those into the procedure call; e.g.:
declare
l_rec rec_arr;
l_cur sys_refcursor;
begin
l_rec := rec_arr(rec_typ('Joe','Bloggs'), rec_typ('Mary','Berry'));
get_emp_pkg.get_emp(l_rec, l_cur);
-- do something with the cursor
close l_cur;
end;
/
If you are just testing it and you're using SQL*Plus or SQL Developer you could simplify this to use a client bind variable:
variable cur refcursor;
declare
l_rec rec_arr;
begin
l_rec := rec_arr(rec_typ('Joe','Bloggs'), rec_typ('Mary','Berry'));
get_emp_pkg.get_emp(l_rec, :cur);
end;
/
print cur;
or even more simply:
variable cur refcursor;
begin
get_emp_pkg.get_emp(rec_arr(rec_typ('Joe','Bloggs'), rec_typ('Mary','Berry')), :cur);
end;
/
print cur;
and you could even replace that with an execute call, which is just a wrapper for an anonymous block anyway, so functionally almost identical.
Your procedure has a mistake though; you're declaring a local l_out variable and then opening the ref cursor based on that, but you don't ever populate it - so the ref cursor result set will always be empty. If you change it to use l_rec instead (though I would call that p_rec, with the p_ prefix indicating a parameters and leave the l_ prefix for local variables):
create or replace package body get_emp_pkg
as
procedure get_emp
(
l_rec rec_arr,
p_out out sys_refcursor
)
as
begin
open p_out for select * from table ( l_rec );
end get_emp;
end;
/
then the bind variable versions above both see:
PL/SQL procedure successfully completed.
FNAME LNAME
---------- ----------
Joe Bloggs
Mary Berry

Create stored procedure which returns in one OUT param database version (Oracle)

I new with PL\SQL so i'm traying to make a procedure witch return database version with OUT in one param. My SQL code is:
CREATE OR REPLACE PROCEDURE getVersion(outParam1 OUT VARCHAR2)
IS
BEGIN
outParam1 := SELECT * FROM V$VERSION;
END;
Can some one explain me how to write procedure right way and how to execute the procedure.
Try as
CREATE OR REPLACE PROCEDURE getVersion (out_cursor OUT SYS_REFCURSOR)
AS
BEGIN
OPEN out_cursor FOR SELECT * FROM V$VERSION;
EXCEPTION
WHEN NO_DATA_FOUND
THEN
DBMS_OUTPUT.put_line (SQLERRM);
WHEN OTHERS
THEN
DBMS_OUTPUT.put_line (SQLERRM);
END getVersion;
In order to execute from SQL Plus, do as
VARIABLE mycursor REFCURSOR;
BEGIN
getVersion (:mycursor);
END;
/
PRINT mycursor
From SQL Developer do as
var mycursor refcursor
exec getVersion(:mycursor)
print mycursor
If you would like to have OUT varchar2 with a single row, then you could something like
CREATE OR REPLACE PROCEDURE myProc (outParam1 OUT VARCHAR2)
AS
BEGIN
SELECT dummy INTO outParam1 FROM DUAL;
EXCEPTION
WHEN NO_DATA_FOUND
THEN
DBMS_OUTPUT.put_line (SQLERRM);
WHEN OTHERS
THEN
DBMS_OUTPUT.put_line (SQLERRM);
END myProc;
and execute as
VARIABLE testvar VARCHAR2(16);
EXEC myProc(:testvar);
PRINT testvar;

How do I return a SYS_REFCURSOR from a stored procedure after a loop?

I am a bit new to Oracle and PL SQL. I have a procedure like the following.
{
CREATE OR REPLACE PROCEDURE MyProcedure (MyRecordset OUT SYS_REFCURSOR)
AS
BEGIN
DECLARE
CURSOR MyRecordset IS
select
...
from table1, table2, etc..
BEGIN
FOR Record in MyRecordset
LOOP
--Do something
END LOOP; -- IMPLICIT CLOSE OCCURS
-- THIS IS WHERE I NEED TO RETURN THE CURSOR. DOES THIS NOT OPEN IT AT BEGINNING AGAIN?
OPEN MyRecordset;
END;
END MyProcedure;
/
}
I need to return a SYS_REFCURSOR. Is this sufficient? When I try to test it with the following in Toad I get no output in the data grid.
{
DECLARE
type result_set is ref cursor;
BEGIN
BIZTALK.GetCustomerPaymentsDebug(:result_set);
END;
}
This example works for me. I think it should help you.
Declare cursor like:
TYPE genCurType IS REF CURSOR;
PROCEDURE return_in
( p_ime IN VARCHAR2
, po_seznam OUT genCurType
, po_errid OUT errorIdType
, po_errmsg OUT errorMsgType
)
IS
cc_module_name CONSTANT VARCHAR2(60):= 'return_ins';
BEGIN
OPEN po_seznam FOR SELECT IME, OPIS, NAZIV, OBRAZEC
FROM test
WHERE upper(IME) = upper(p_ime);
EXCEPTION
WHEN OTHERS THEN
po_errid := SQLCODE;
po_errmsg := 'Poizvedba ni bila uspešna! ('||SQLERRM||''||gc_package||'.'||cc_module_name||')';
END;

Returning a cursor , calling a procedure from other procedure

I have 2 procedures in same package.
I wish to use QOT_LST_M_QOT_PRE in QOT_LST_M_SEC_EXC_PRE. In QOT_LST_M_SEC_EXC_PRE I wish to find the argument - x_qot_id, call QOT_LST_M_QOT_PRE with this argument and also return it instead of the statement. Can I do it? How.
I mean something like
PROCEDURE QOT_LST_M_SEC_EXC_PRE (
i_sec_id IN NUMBER,
i_exc_id IN NUMBER,
o_recordset OUT SYS_REFCURSOR ) IS x_qot_id NUMBER(10);
------------------------------
BEGIN
---------------------------------------------------------------
--call a function instead of writing query from this function
open o_recordset for QOT_LST_M_QOT_PRE(x_qot_id, o_recordset);
----------------------------------------------------------------
END QOT_LST_M_SEC_EXC_PRE;
PROCEDURE QOT_LST_M_QOT_PRE
(
i_qot_id IN NUMBER,
o_recordset OUT SYS_REFCURSOR
--------------------------------
);
Sure you can. You can declare out parameters of type SYS_REFCURSOR and use them in your procedures, here is an example:
CREATE OR REPLACE PROCEDURE QOT_LST_M_QOT_PRE (i_qot_id IN NUMBER, THE_CURSOR OUT SYS_REFCURSOR) --Declare a sys_refcursor to be an out parameter, so it can be used outside
AS
BEGIN
OPEN THE_CURSOR FOR SELECT * FROM THE_TABLE WHERE X=i_qot_id;--Open the cursor
END;
CREATE OR REPLACE PROCEDURE QOT_LST_M_SEC_EXC_PRE (i_sec_id IN NUMBER, i_exc_id IN NUMBER)
AS
x_qot_id NUMBER(10); --Test param
RESULT_CURSOR SYS_REFCURSOR;--The cursor that will hold the opened cursor in QOT_LST_M_QOT_PRE procedure
SOMEVARIABLE VARCHAR2(10);--Test variables to hold results of cursor
BEGIN
QOT_LST_M_QOT_PRE(1,RESULT_CURSOR);--Procedure will open RESULT_CURSOR
LOOP --Loop cursor
FETCH RESULT_CURSOR INTO SOMEVARIABLE;
EXIT WHEN RESULT_CURSOR%NOTFOUND;
DBMS_OUTPUT.PUT_LINE('READ :'||SOMEVARIABLE);
END LOOP;
CLOSE RESULT_CURSOR;--Close the opened cursor
END;