Calling SP with sys_refcursor as out parameter inside another procedure - oracle

I have an SP
create or replace PROCEDURE ALTERNATE_NAME_LOOKUP
( P_NAME IN VARCHAR2,
P_TYPE IN VARCHAR2, retCursor OUT SYS_REFCURSOR
)
I didn't paste the rest of its body; The above procedure works fine on its own (with the body of course)
Now I want to call it from another stored procedure, and I want to traverse over the refcursor.
What I am doing is declaring an_last_cur SYS_REFCURSOR; and calling ALTERNATE_NAME_LOOKUP procedure as ALTERNATE_NAME_LOOKUP(p_req.LASTNAMEEXP,c_LAST, an_last_cur); It compiles.
but when I add following block -
ALTERNATE_NAME_LOOKUP('Roman Reigns','LAST',an_last_cur);
For alt in an_last_cur
Loop
DBMS_OUTPUT.PUT_LINE('ok');
end loop;
It gives compilation error -
PLS-00221: 'AN_LAST_CUR' is not a procedure or is undefined
What am I doing wrong?

create or replace procedure alternate_name_lookup
( p_name in varchar2, p_type in varchar2, retcursor out sys_refcursor )
as
begin
open retcursor for select * from user_objects ;
end;
set serveroutput on
declare
an_last_cur sys_refcursor;
type my_objects is table of user_objects%rowtype;
objects my_objects;
begin
alternate_name_lookup('Roman Reigns','LAST',an_last_cur);
fetch an_last_cur bulk collect into objects;
dbms_output.put_line(objects.count);
for indx in 1 .. objects.count
loop
dbms_output.put_line(objects(indx).object_name);
end loop;
close an_last_cur;
end;

Try this one. Hope this helps. I dont have workspace with me so pardon
syntax erro r if any.
CREATE OR REPLACE PROCEDURE test_ref_prc
( p_ref_out OUT sys_refcursor)
AS
BEGIN
OPEN p_ref_out FOR
SELECT LEVEL FROM DUAL CONNECT BY LEVEL < 10;
END;
CREATE OR REPLACE PROCEDURE test_ref2
AS
refc sys_refcursor;
num_ntt NUMBER_NTT;
BEGIN
test_ref_prc(refc);
FETCH refc BULK COLLECT INTO num_ntt;
FOR I IN num_ntt.FIRST..num_ntt.LAST LOOP
dbms_output.put_line(num_ntt(i));
END LOOP;
END;
exec test_ref2;

Related

How to pass cursor rowtype between procedures in package

I have an explicit cursor in package, I create rowtype based on this cursor, how can I pass this rowtype between procedures?
My exmaple hung up when compile.
cursor cur(param) is
select * from dual where param = 1;
rec cur%rowtype;
procedure do_something_with_rec(p_rec in cur%rowtype)
is
begin
dbms_output.put_line(p_rec.dummy);
end;
procedure main(param)
is
begin
open cur(param);
loop
fetch into rec;
exit when cur%notfound;
end loop;
close cur;
do_something_with_rec(rec);
end;
You forgot to add parameter types in cursor, definition of procedure main and in fetch add cursor name. This package compiled and worked:
-- package
create or replace package p_test is
procedure main(param in number);
end p_test;
-- body
create or replace package body p_test is
cursor cur(param in number) is select * from dual where param = 1;
rec cur%rowtype;
procedure do_something_with_rec(p_rec in cur%rowtype) is
begin
dbms_output.put_line(p_rec.dummy);
end;
procedure main(param in number) is
begin
open cur(param);
loop
fetch cur into rec;
exit when cur%notfound;
end loop;
close cur;
do_something_with_rec(rec);
end;
end p_test;

How can I return dataset in procedure?

I have a procedure like this:
CREATE OR REPLACE PROCEDURE RIC.TEST
(P_VAR1 IN VARCHAR2, P_VAR2 IN VARCHAR2, P_VAR3 IN VARCHAR2, P_VAR4 IN VARCHAR2)
IS
L_RC SYS_REFCURSOR;
BEGIN
INSERT INTO RIC.TEMP_TABLE
SELECT * FROM RIC.TABLE WHERE COL1=P_VAR1 AND COL2=P_VAR2 AND COL3=P_VAR3 AND COL4=P_VAR4 AND ...;
OPEN L_RC
FOR 'SELECT .... FROM RIC.TEMP_TABLE WHERE ...';
...
TEMP_TABLE is a temporary table. I need to return and show second select output (SELECT .... FROM RIC.TEMP_TABLE WHERE ...) when I run this procedure. How can I do that? Is cursor wrong way for this?
Thank you.
Modify the procedure to
CREATE OR REPLACE PROCEDURE ric.test (p_var1 IN VARCHAR2,
p_var2 IN VARCHAR2,
p_var3 IN VARCHAR2,
p_var4 IN VARCHAR2,
p_cursor OUT SYS_REFCURSOR)
IS
BEGIN
INSERT INTO ric.temp_table
SELECT *
FROM ric.table
WHERE col1 = p_var1 AND col2 = p_var2 AND col3 = p_var3;
OPEN p_cursor FOR SELECT * FROM ric.temp_table;
END;
/
and execute the procedure as
VARIABLE cur REFCURSOR;
EXEC test (:cur);
PRINT cur;
If you would like to execute the procedure using SQL, wrap the procedure in a function which should be followed by calling the function in a SQL statement.
Example

Trying to understand how pl sql stored proc work and why my results differ

I have a simple stored proc...
create or replace
PROCEDURE GET_PERSON (aName VARCHAR2, p_data OUT sys_refcursor)
IS
BEGIN
OPEN p_data FOR SELECT * FROM people_table WHERE firstname = aName;
END;
However when I execute the stored proc it returns all of the records.
DECLARE
v_cur SYS_REFCURSOR;
v_1 number;
v_2 VARCHAR2(50);
v_3 VARCHAR2(200);
v_4 VARCHAR2(50);
v_5 VARCHAR2(50);
v_6 VARCHAR2(50);
BEGIN
GET_PERSON ('aaa#bbb.com', v_cur);
LOOP
FETCH v_cur INTO v_1, v_2, v_3, v_4, v_5, v_6;
EXIT WHEN v_cur%NOTFOUND;
dbms_output.put_line(v_2 || ' ' || v_3);
END LOOP;
CLOSE v_cur;
END;
If I run the simple statement
SELECT * FROM people_table WHERE firstname = 'aaa#bbb.com';
It correctly returns one record.
Why is the stored proc not behaving the same?
I found the issue..
My issue was name collision. When I altered the code above is when I noticed the issue. I originally has WHERE fistname = firstName. Once I changed the parameter to p_firstName as was well.

Procedure to input number and output varchar2

I need to write a procedure to input let's say a rep_id and then output the rep_name that corresponds to the rep_id.
After that, I need to use another procedure to call the above procedure.
Here is what I have for the first procedure.
create or replace procedure p_inout
(v_rep_id in number)
As
v_first_name varchar2(20);
v_last_name varchar2(20);
begin
select first_name,last_name into v_first_name, v_last_name
from rep
where rep_id = v_rep_id;
dbms_output.put_line(v_first_name||' '||v_last_name);
end p_inout;
/
Execute p_inout(100);
And here is my procedure to call the above procedure
create or replace procedure p_call
is
v_first_name varchar2(20);
v_last_name varchar2(20);
begin
p_inout(100);
dbms_output.put_line(v_first_name||' '||v_last_name);
end p_call;
/
execute p_call
I was able to get the result but one guy told me that my call procedure should be like this
Create or replace procedure p_call
Is
V_name varchar2(20);
Begin
P_inout(100,v_name); --100 is a rep id
Dbms_output.Put_line(v_name);
End;
/
Execute p_call
Doesn't my procedure to call and his call procedure produce the same result?
CREATE TABLE minions (
rep_id DATE CONSTRAINT minions__rep_id__pk PRIMARY KEY,
rep_name NUMBER CONSTRAINT minions__rep_name__nn NOT NULL
CONSTRAINT minions__rep_name__u UNIQUE
)
/
CREATE OR REPLACE PROCEDURE myCatWasSick (
p_rep_id IN minions.rep_id%TYPE,
p_rep_name OUT minions.rep_name%TYPE
)
IS
BEGIN
SELECT rep_name
INTO p_rep_name
FROM minions
WHERE rep_id = p_rep_id;
EXCEPTION
WHEN NO_DATA_FOUND THEN
p_rep_name := NULL;
END myCatWasSick;
/
CREATE OR REPLACE PROCEDURE releaseTheBadgers
IS
the_badger NUMBER(10);
BEGIN
myCatWasSick( SYSDATE + 1, the_badger );
// Do something with the_badger.
END releaseTheBadgers;
/

PL/SQL print out ref cursor returned by a stored procedure

How can I fetch from a ref cursor that is returned from a stored procedure (OUT variable) and print the resulting rows to STDOUT in SQL*PLUS?
ORACLE stored procedure:
PROCEDURE GetGrantListByPI(p_firstname IN VARCHAR2, p_lastname IN VARCHAR2,
p_orderby IN VARCHAR2, p_cursor OUT grantcur);
PL/SQL:
SET SERVEROUTPUT ON;
DECLARE
TYPE r_cursor IS REF CURSOR;
refCursor r_cursor;
CURSOR grantCursor IS
SELECT last_name, first_name
FROM ten_year_pis
WHERE year_added = 2010;
last_name VARCHAR2(100);
first_name VARCHAR2(100);
BEGIN
OPEN grantCursor;
FETCH grantCursor INTO last_name, first_name;
WHILE grantCursor%FOUND LOOP
PMAWEB_PKG.GetGrantListByPI(last_name, first_name, 'last_name', refCursor);
--HOW DO I LOOP THROUGH THE RETURNED REF CURSOR (refCursor)
--AND PRINT THE RESULTING ROWS TO STDOUT?
FETCH grantCursor into last_name, first_name;
END LOOP;
CLOSE grantCursor;
END;
/
Note: This code is untested
Define a record for your refCursor return type, call it rec. For example:
TYPE MyRec IS RECORD (col1 VARCHAR2(10), col2 VARCHAR2(20), ...); --define the record
rec MyRec; -- instantiate the record
Once you have the refcursor returned from your procedure, you can add the following code where your comments are now:
LOOP
FETCH refCursor INTO rec;
EXIT WHEN refCursor%NOTFOUND;
dbms_output.put_line(rec.col1||','||rec.col2||','||...);
END LOOP;
You can use a bind variable at the SQLPlus level to do this. Of course you have little control over the formatting of the output.
VAR x REFCURSOR;
EXEC GetGrantListByPI(args, :x);
PRINT x;
If you want to print all the columns in your select clause you can go with the autoprint command.
CREATE OR REPLACE PROCEDURE sps_detail_dtest(v_refcur OUT sys_refcursor)
AS
BEGIN
OPEN v_refcur FOR 'select * from dummy_table';
END;
SET autoprint on;
--calling the procedure
VAR vcur refcursor;
DECLARE
BEGIN
sps_detail_dtest(vrefcur=>:vcur);
END;
Hope this gives you an alternate solution
More easier option is to use DBMS_SQL.return_result();
Lets say your package / procedure / cursor spec is as below.
create or replace PACKAGE my_package IS
TYPE my_ref_cursor_type IS REF CURSOR;
PROCEDURE my_procedure (
p_in_param1 IN VARCHAR2,
p_in_param2 IN VARCHAR2,
p_in_param3 IN VARCHAR2,
p_my_ref_cursor OUT my_ref_cursor_type,
p_err_code OUT NUMBER,
p_err_msg OUT VARCHAR2
);
END my_package;
Try this to invoke the procedure from your sql developer WORKSHEET
SET SERVEROUTPUT ON;
DECLARE
P_MY_REF_CURSOR my_schema.my_package.my_ref_cursor_type;
P_ERR_CODE NUMBER;
P_ERR_MSG VARCHAR2(200);
BEGIN
my_package.my_procedure(
'VALUE1',
'VALUE2',
'VALUE3',
P_MY_REF_CURSOR => P_MY_REF_CURSOR,
P_ERR_CODE => P_ERR_CODE,
P_ERR_MSG => P_ERR_MSG
);
DBMS_OUTPUT.PUT_LINE(P_ERR_MSG);
DBMS_OUTPUT.PUT_LINE(P_ERR_CODE);
DBMS_SQL.return_result(P_MY_REF_CURSOR);
END;
Hope this helps !
There are many ways for displaying the sys_refcursor result set and one of them that is so easy is using SQL Developer to fetch sys_refcursor and print output which are:
Create a test function to print its result
Execute the function
View the output
Verify the result set

Resources