Get Ref Cursor from dbms_sql.open_cursor - oracle

I have been asked to try to fix some existing PL/SQL code at work and I am new to PL/SQL. I am sorry if this is a stupid question.
Is there a way to take the cursor id returned by dbms_sql.open_cursor and get a REF CURSOR? Something like this:
procedure DoSomething (po_cursor out REF CURSOR) is
lv_cursorid integer;
begin
lv_cursorid := DBMS_SQL.open_cursor;
po_cursor := get_cursor_by_id(lv_cursorid);
end;

Per the docs, dbms_sql.to_refcursor(lv_cursorid) should do it

Related

How to draw the line that triggered the trigger pl/sql?

This is my code:
CREATE OR REPLACE TRIGGER TR_DEL
AFTER INSERT OR UPDATE
ON DIZIONARIO_CHIAVI_DA_ESCLUDERE
FOR EACH ROW
DECLARE
CURSOR c_cursore_prendi_riga IS
SELECT CURRICULUM_CHIAVE_RICERCA
FROM PERSONA;
myCursor PERSONA.CURRICULUM_CHIAVE_RICERCA%TYPE;
BEGIN
OPEN c_cursore_prendi_riga;
LOOP
FETCH c_cursore_prendi_riga INTO myCursor;
EXIT WHEN c_cursore_prendi_riga%NOTFOUND;
dbms_output.put_line('oo='|| myCursor );
-- Here I need it
END LOOP;
CLOSE c_cursore_prendi_riga;
END;
I need the row that started the trigger, thanks
Nicholas Krasnov is right, to put this in an answer:
:new and :old are used as pseudo-records. Documentation is here:
https://docs.oracle.com/database/121/TDDDG/tdddg_triggers.htm#TDDDG50000
and here the explanation of these pseudo-records:
https://docs.oracle.com/database/121/LNPLS/triggers.htm#LNPLS99955
Most important: pseudo-records can not used like "normal" records. You have to name each column...
For example you can not use:
my_special_function(:new);
You wil have to create a "real" record:
declare
myrec mytable%rowtype;
begin
myrec.id := :new.id;
myrec.name := :new.name;
myrec.birthdate := :new.birthdate;
etc etc etc
my_special_function(myrec);
end

How to build a dynamic PLSQL query to fetch records?

I am trying to create a stored procedure in Oracle and make a dynamic query work to get a bunch of records. I have read many examples but so far I can't get this to work unless I do this:
CREATE OR REPLACE PROCEDURE GiveMeResultSet(
v_par1 IN CHAR,
v_par2 IN CHAR,
v_par3 IN CHAR,
v_par4 IN VARCHAR2,
v_par5 IN VARCHAR2,
v_par6 IN VARCHAR2,
cur_typ OUT SYS_REFCURSOR)
IS
BEGIN
OPEN cur_typ FOR 'select * from complex_query';
--CLOSE cur_typ;
END;
And I am executing it this way:
var c refcursor;
execute GiveMeResultSet(null,null,null,null,null,null,:c);
print c;
This way I get the header names and the records from the query, but I am not closing the cursor that is fetching the results. If I close it then I get nothing at all. I guess leaving it open could cause some kind of memory leak problem at some point.
I have seen similar cases in Oracle documentation where they do something like this:
sql_stmt := 'SELECT * FROM emp';
OPEN emp_cv FOR sql_stmt;
LOOP
FETCH emp_cv INTO emp_rec;
EXIT WHEN emp_cv%NOTFOUND;
-- process record
END LOOP;
CLOSE emp_cv;
But I have no clue what goes on the "process record" part of the code which would allow to get the whole set of records at the end, plus that my record has a complex structure that doesn't fit with a fixed set of fields as in a table.
Can you please show me the proper way to do this?.
Thanks a lot.
ok CodeRoller, here is my sample code for a unspecified ref cursor:
Code of the Function which returns the ref cursor:
create or replace function test_ref_cursor(pi_sql_statement in varchar2) return SYS_REFCURSOR is
result_cursor SYS_REFCURSOR;
begin
open result_cursor for pi_sql_statement;
return result_cursor;
end;
Now, in the next step I use this function to get data from v$parameter:
declare
type t_my_cursor is ref cursor;
my_cursor t_my_cursor;
l_rec v$parameter%rowtype;
begin
my_cursor := test_ref_cursor('select * from v$parameter');
loop
fetch my_cursor into l_rec;
exit when my_cursor%notfound;
dbms_output.put_line(l_rec.name || ' = ' || l_rec.value);
end loop;
close my_cursor;
end;
Take care, to close the ref-cursor!

How to declare / assign a variable to a cursor type in PL/SQL procedure

I have two cursors declared in a stored procedure (inside a package).
procedure RECONCILE_CC_TRX (p_to_date in date,
p_nz_flag in varchar2,
p_Reconcile_Header_ID out NUMBER
) is
CURSOR LOADED_TRXS_AU IS
SELECT
CC_REC_LOAD_TRX_ID,
CC_REC_LOAD_HEADER_ID,
....
CURSOR LOADED_TRXS_NZ IS
SELECT
CC_REC_LOAD_TRX_ID,
CC_REC_LOAD_HEADER_ID,
The only difference between the two cursors is the where clause.
What I want to do, is open one of those cursors based on the p_nz_flag passed in above. ie:
IF NVL(p_nz_flag, 'F') = 'F' THEN
v_load_trx_cursor := LOADED_TRXS_AU;
ELSE
v_load_trx_cursor := LOADED_TRXS_NZ;
END IF;
FOR bitem IN v_load_trx_cursor LOOP
...
My initial thinking was to declare a variable and assign it the appropriate cursor, however, I can't get the procedure to compile with this. eg, I have tried:
v_load_trx_cursor sys_refcursor;
but I get a compilation error when assigning v_load_trx_cursor of "PLS-00382: Expression is of wrong type". If I change my declaration to:
v_load_trx_cursor cursor;
I get compilation error at the declaration point stating "PLS-00201: Identifier 'Cursor' must be declared.
Is it possible to do what I want to do? At the end of the day, I just want to iterate the appropriate cursor based on the p_nz_flag parameter passed in.
Thanks
It looks like you want to use only one cursor in your code, based on the value of p_nz_flag
In this case, believe it will be better to make the where clause dynamically in your code and then use refcursor to return the data of the query.
Something like given in Example 7-4 on this link Dynamic Query with Refcursor
Hope it Helps
Vishad
Hi if your whole work for doing this procedure is just to populate the appropriate cursor i think this code may help you.
CREATE OR REPLACE PROCEDURE av_nst_cursor(
flag_in IN VARCHAR2,
av_cur OUT sys_refcursor)
AS
BEGIN
IF flag_in = 'Y' THEN
OPEN av_cur FOR SELECT Query;
ELSE
OPEN av_cur FOR SELECT query;
END IF;
END;

How to test PL/SQL procs involving arrays from Toad?

I have a need to test a stored procedure involving arrays that are written in PL/SQL. I have no way of seeing the PL/SQL contents (shop rules) but need to call the proc. I'd like to know how to call the following proc that invovles 3 arrays of integers directly from toad. The method signature looks like this.
Procedure persistChanges(myKey in NUMBER, arrayOfIntsFirst numberTableType, arrayOfIntsSecond numberTableType, arrayOfIntsThird numberTableType).
How can I call a PL/SQL proc in TOAD where I can hard-code the values for the paramters to test the proc? I'm told there's no way this could be done in Toad. Much appreciated!!!
I have to believe there's a way to poplate these variables but just not sure how to go about doing so...
DECLARE
myKey NUMBER;
arrayOfIntsFirst PL/SQL TABLE;
arrayOfIntsSecond PL/SQL TABLE;
arrayOfIntsThird PL/SQL TABLE;
BEGIN
myKey := NULL;
-- arrayOfIntsFirst := NULL; Modify the code to initialize this parameter
-- arrayOfIntsSecond := NULL; Modify the code to initialize this parameter
-- arrayOfIntsThird := NULL; Modify the code to initialize this parameter
MY_SCHEMA.PKG_MYPACKAGE.PERSISTCHANGES ( myKey, arrayOfIntsFirst,
arrayOfIntsSecond, arrayOfIntsThird );
COMMIT;
END;
Try something like:
declare
l_nums t_num_tab;
begin
l_nums := t_num_tab();
l_nums.extend(2);
l_nums(1) := 56;
l_nums(2) := 42;
for i in l_nums.first .. l_nums.last
loop
dbms_output.put_line( 'Number is: ' || l_nums(i) );
end loop;
end;
And Toad is just a development environment, it won't limit you from writing an anonymous block like above. The t_num_tab is defined as a table of numbers:
CREATE OR REPLACE TYPE t_num_tab as table of number;
You don't even need to formally extend the collection first and assign values. You can initialize in one step:
declare
l_nums t_num_tab;
begin
l_nums := t_num_tab(23,89,152);
...
end;
Read more here. Hope that helps.

How do I return the rows from an Oracle Stored Procedure using SELECT?

I have a stored procedure which returns a ref cursor as follows:
CREATE OR REPLACE PROCEDURE AIRS.GET_LAB_REPORT (ReportCurTyp OUT sys_refcursor)
AS
v_report_cursor sys_refcursor;
report_record v_lab_report%ROWTYPE;
l_sql VARCHAR2 (2000);
BEGIN
l_sql := 'SELECT * FROM V_LAB_REPORT';
OPEN v_report_cursor FOR l_sql;
LOOP
FETCH v_report_cursor INTO report_record;
EXIT WHEN v_report_cursor%NOTFOUND;
END LOOP;
CLOSE v_report_cursor;
END;
I want to use the output from this stored procedure in another select statement like:
SELECT * FROM GET_LAB_REPORT()
but I can't seem to get my head around the syntax.
Any ideas?
Whenever I've had to do this; I've used the Oracle TYPE and CAST features.
Something like:
SELECT *
FROM TABLE(CAST(F$get_Cassette_Tracking('8029241') AS cass_tracking_tab_type))
You need to setup the TYPE and all the columns you need and have them use:
pipe ROW(out_obj)
to capture your data. There are many ways to do this and if I can dig out a better example I will but this might give you an idea.
See this SO for a working example: Oracle Parameters with IN statement?

Resources