How to display table from returned cursor in Oracle? - sql

I need to get a table of bank's name which their bsb is equal to value given to the function.
Here is my code:
CREATE OR REPLACE Function FF(BSB_NUMBER IN BANK.BSB#%TYPE) RETURN SYS_REFCURSOR
IS
MY_CURSOR SYS_REFCURSOR;
BEGIN
OPEN MY_CURSOR for
select * from bank where bank.bsb# = BSB_NUMBER;
return MY_CURSOR;
EXCEPTION
WHEN NO_DATA_FOUND THEN
DBMS_OUTPUT.PUT_LINE('Error ! There is no such account');
END FF;
/
And I run in with this but doesn't print anything. Appreciate any idea:
SELECT FindBankStaff(012878) FROM BANK;

Don't return the cursor, return the appropriate value.

Finally I saw this answer and implement it to my issue:
CREATE OR REPLACE FUNCTION SOME_FUNC_RETURNING_A_CURSOR RETURN SYS_REFCURSOR IS
csrLocal SYS_REFCURSOR;
BEGIN
OPEN csrLocal FOR SELECT NAME, BSB# FROM BANK;
RETURN csrLocal;
END SOME_FUNC_RETURNING_A_CURSOR;
/
DECLARE
aCursor SYS_REFCURSOR;
someVariable VARCHAR2(40);
some2 number;
BEGIN
aCursor := SOME_FUNC_RETURNING_A_CURSOR;
WHILE TRUE LOOP
FETCH aCursor INTO someVariable,some2;
EXIT WHEN aCursor%NOTFOUND;
DBMS_OUTPUT.PUT(someVariable);
DBMS_OUTPUT.PUT(' ');
DBMS_OUTPUT.PUT_LINE(some2);
END LOOP;
COMMIT;
END;
/

In Toad there is an option to do this.
You just have to create a bind variable as Ref cursor and invoke the procedure or function. Once the process runs successfully, the Data Grid is automatically populated with the result set of the Object (In your case the records from ref cursor). I suppose even in Oracle Sql Developer the Feature has been incorporated.
If you are using SQL Plus* then the best way is to declare a variable as ref cursor. Execute the piece of block and print the output using print command. Hope it helps...

Related

Oracle procedure with SYS_REFCURSOR as OUT parameter displays only old values

I created the following table called APP_USERS with nine columns:
I want to get all data from a single record by calling a procedure with SYS_REFCURSOR as OUT parameter: The code looks like that:
create or replace PACKAGE BODY USER_LOGIN AS
PROCEDURE getUserToLogIn(comp_id NUMBER, user_id APP_USERS.USER_ID%TYPE, pass APP_USERS.ACC_PASSWORD%TYPE, v_IS_ADMIN IN char,
curs out sys_refcursor)
IS
lala APP_USERS%ROWTYPE;
BEGIN
OPEN curs FOR
SELECT USER_ID,FIRST_NAME,MIDDLE_NAME,LAST_NAME,SEX,COMPANY_ID,IS_ADMIN,ACC_PASSWORD,IS_ACTIVE
FROM APP_USERS
WHERE COMPANY_ID = comp_id and USER_ID = TRIM(user_id) and ACC_PASSWORD = pass and IS_ADMIN = v_IS_ADMIN;
DBMS_OUTPUT.PUT_LINE(comp_id);
DBMS_OUTPUT.PUT_LINE(user_id);
DBMS_OUTPUT.PUT_LINE(pass);
DBMS_OUTPUT.PUT_LINE(v_IS_ADMIN);
DBMS_OUTPUT.PUT_LINE('--------------------------------------');
LOOP
FETCH curs INTO lala;
exit when curs%notfound;
DBMS_OUTPUT.PUT_LINE(lala.USER_ID);
DBMS_OUTPUT.PUT_LINE(lala.COMPANY_ID);
DBMS_OUTPUT.PUT_LINE(lala.ACC_PASSWORD);
DBMS_OUTPUT.PUT_LINE(lala.IS_ADMIN);
END LOOP;
CLOSE curs;
END getUserToLogIn;
END USER_LOGIN;
At first I called a procedure by running a simple anonymous block like below:
declare
curs sys_refcursor;
begin
USER_LOGIN.getUserToLogIn(1000,'EU1002','UCFE3M0N','N',curs);
end;
and I got the following results:
Next time I run the anonymous block again with wrong data, so that the procedure could not find them, but the result was not correct:
At first time, when I entered correct data my procedure displayed them, but the second attempt with wrong data entered caused displaying the data from the previous one.
My question is why:
exit when curs%notfound;
is this part of the code overlooked?
That not the proper way to use a refcursor. Here is a simplified example from your code:
create or replace PROCEDURE getUserToLogIn( user_id APP_USERS.USER_ID%TYPE,
curs in out sys_refcursor)
IS
BEGIN
OPEN curs FOR SELECT * FROM APP_USERS; -- where blah, blah
end ;
declare
lala APP_USERS%ROWTYPE;
my_cursor sys_refcursor;
begin
getUserToLogIn('xxx', my_cursor);
LOOP
FETCH my_cursor INTO lala;
exit when my_cursor%notfound;
DBMS_OUTPUT.PUT_LINE('output= ' || lala.USER_ID);
end loop;
close my_cursor;
end;
So the standard method is you call the procedure that creates the SELECT statement you need, then just OPEN cursor parameter. The caller then gets the cursor back, iterates thought it, then closes it.
Heres also a tutorial.

Use the value of a string variable in SQL FOR-IN (SELECT) loop

I have an SQL procedure, that should execute a FOR-IN (SELECT ..) loop, where the SELECT content should vary depending on some input parameters. My idea was to store the SELECT string into a variable, and then try to extract the variable value in the FOR-IN loop but without success so far (earlier there was a fix SELECT statement used there, that's what I am trying to replace now). The code looks about as follows
PROCEDURE run(p_boolean BOOLEAN)
IS
BEGIN
DECLARE
v_mystring VARCHAR(50);
BEGIN
IF p_boolean = TRUE
THEN
v_mystring := 'SELECT something...';
ELSE
v_mystring := 'SELECT something else...';
END IF;
FOR p_table_name IN (would-like-to-use-the-value-of-v_mystring-here-some-way)
LOOP
...
END LOOP;
END;
END;
Being quite novice in SQL, it might well happen that the entire concept of trying to use a string variable value here is wrong. I browsed through some tutorials and tried some other ideas (e.g. cursor), but no result. Any idea is appreciated
Assuming Oracle's PL/SQL ,You can open a REFCURSOR using dynamic String and call it in a LOOP..
PROCEDURE run(p_boolean BOOLEAN)
IS
BEGIN
DECLARE
v_mystring VARCHAR(50);
v_my_ref_cursor sys_refcursor;
BEGIN
IF p_boolean = TRUE
THEN
v_mystring := 'SELECT something...';
ELSE
v_mystring := 'SELECT something else...';
END IF;
OPEN v_my_ref_cursor FOR v_mystring;
LOOP
FETCH v_my_ref_cursor INTO your_variables/record
EXIT WHEN v_my_ref_cursor%NOTFOUND;
..
END LOOP;
CLOSE v_my_ref_cursor;
END;
END;

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;

How can I fetch the data from the SYS_REFCURSOR from one stored proc and use it in another?

I have a stored proc with the basic layout below that returns a sys_refcursor as a result set. (Technically it reurns four but for the sake of clarity I just say one). The result set is a selection from a temp table.
procedure aProcedure
( C1 in out sys_refcursor
) is
begin
--populate Temp_Table here with a stored proc call;
OPEN C1 FOR
SELECT Cols
FROM TEMP_TABLE;
I need to insert this result set from C1 into a permanent table using a different stored procedure. Is this Do-able or do I need to re-build the result set all over again?
I've been able to find information on working with cursors and result sets outside of oracle but not for working with them within itself.
I know it might make sense to just do the insert from the first stored proc but that's not really how I need it to happen. It's an optional requirement to save the result set permanently.
Thanks for any helpful info.
Assuming that the caller knows the structure of the cursor that aProcedure is opening, you can do something like this.
declare
l_rc sys_refcursor;
l_rec temp_table%rowtype;
begin
aProcedure( l_rc );
loop
fetch l_rc
into l_rec;
exit when l_rc%notfound;
dbms_output.put_line( l_rec.col1 );
end loop;
close l_rc;
end;
/
If you can't fetch into a record type, you can also fetch into a number of other scalar local variables (the number and type have to match the number and type of columns that aProcedure specifies in its SELECT list). In my case, I defined aProcedure to return two numeric columns
declare
l_rc sys_refcursor;
l_col1 number;
l_col2 number;
begin
aProcedure( l_rc );
loop
fetch l_rc
into l_col1, l_col2;
exit when l_rc%notfound;
dbms_output.put_line( l_col1 );
end loop;
close l_rc;
end;

Get all records from a Ref Cursor in a Package

I'd like to fetch each row when I call the following function:
CpuReporting.getgridusage(300)
This function was provided in a CpuReporting package. It has:
Function GetGridUsage(minutes_Input in Number) Return CurGridUsage;
Type CurGridUsage is Ref Cursor Return RecGridUsage;
Type RecGridUsage is Record (ConfigId Number,
Phase VarChar2(400),
Environment VarChar2(400),
SessionStartTime Date,
I've browsed the GetGridUsage function in PL/SQL Developer, it has two parameters: (Result) REF CURSOR and MINUSTES_INPUT IN NUMBER
I want to be able to fetch all the rows and since I haven't worked with Ref Cursor before, I'm really interested in knowing how will you going to write the PL/SQL.
Assuming CpuReporting is the package name, you'd want something like
DECLARE
l_cursor CpuReporting.CurGridUsage;
l_rec CpuReporting.RecGridUsage;
BEGIN
l_cursor := CpuReporting.getGridUsage( 300 );
LOOP
FETCH l_cursor INTO l_rec;
EXIT WHEN l_cursor%notfound;
-- Do something with l_rec. As an example, print the Environment
dbms_output.put_line( l_rec.Environment );
END LOOP;
CLOSE l_cursor;
END;
If you just want to see the output of the function in PL/SQL you can do this
var r refcursor;
exec :r := CpuReporting.getgridusage(300);
print r;