What is the alternate of sys_refcursor.
After 12c upgrade, the resultset of sys_refcursor is unrecognizable by mulesoft/tibco. Reading it as null
Use
TYPE cursor_type IS REF CURSOR;
or a strongly typed cursor:
CREATE PACKAGE SCHEMA_NAME.PACKAGE_NAME
AS
TYPE Table_Name_Cursor IS REF CURSOR RETURN SCHEMA_NAME.TABLE_NAME%ROWTYPE;
-- You said this does not work.
-- PROCEDURE get_Weakly_Typed_Cursor (
-- out_cursor OUT SYS_REFCURSOR
-- );
PROCEDURE get_Strongly_Typed_Cursor (
out_cursor OUT Table_Name_Cursor
);
END;
/
CREATE PACKAGE BODY SCHEMA_NAME.PACKAGE_NAME
AS
PROCEDURE get_Strongly_Typed_Cursor (
out_cursor OUT Table_Name_Cursor
)
AS
BEGIN
OPEN out_cursor FOR
SELECT * FROM SCHEMA_NAME.TABLE_NAME;
END;
END;
/
You can define your own ref cursor type:
TYPE my_ref_cursor_type is REF CURSOR;
v_cursor my_ref_cursor_type;
But it would only make sense to do that if using a very old version of Oracle that didn't have SYS_REFCURSOR!
Related
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
Scenario: there is an procedure inside which we have a cursor.
I need to call a function which will take an input from that cursor value and will return SYS_REFCURSOR.
I need to store that result of function in a different variable/cursor & need to return this value from procedure as out parameter.
I am using Oracle 11g.
How can I proceed?
PFB My Approach:
create or replace procedure prc_test
(p_dept_id in number,
c_detail out sysrefcursor)--need to add extra out parameter
as
var1 varchar2(200) :=null;
begin
open c_detail for
select -1 from dual;
if p_dept_id is not null then
open c_detail for
select emp_no from emp
where dept_id=p_dept_id;
--i need to retrn value of 'get_emp_dtls' function as out parameter.
end if;
end procedure;
/
Function to be called
CREATE OR REPLACE FUNCTION get_emp_dtls
(p_emp_no IN EMP.EMP_NO%TYPE)
RETURN SYS_REFCURSOR
AS
o_cursor SYS_REFCURSOR;
BEGIN
OPEN o_cursor FOR
SELECT
ENAME,
JOB
FROM emp
WHERE EMP_NO = p_emp_no;
RETURN o_cursor;
-- exception part
END;
/
Here is your function that takes a varchar2 variable and returns A refcursor( weakly typed).
CREATE OR replace FUNCTION fn_return_cur(v IN VARCHAR2)
RETURN SYS_REFCURSOR
IS
c1 SYS_REFCURSOR;
BEGIN
OPEN c1 FOR
SELECT 'ABC'
FROM dual
WHERE 'col1' = v;
RETURN c1;
END;
/
Here is the procedure that has a cursor value passed as argument to function and the returned cursor passed as OUT argument.
CREATE OR replace PROCEDURE Pr_pass_out_cur(v_2 OUT SYS_REFCURSOR)
IS
func_arg VARCHAR2(3);
other_arg VARCHAR2(3);
CURSOR c_2 IS
SELECT 'ABC' col1,
'DEF' col2
FROM dual;
BEGIN
LOOP
FETCH c_2 INTO func_arg, other_arg;
EXIT WHEN c_2%NOTFOUND;
v_2 := Fn_return_cur(func_arg);
END LOOP;
EXCEPTION
WHEN OTHERS THEN
NULL;
END;
/
Let me know your feedback.
I need a procedure that input user_name and password then get to me the exist tables in that schema with the create script for each table?
This is what I tried, but is wrong:
CREATE OR REPLACE procedure TABLE_INFO(P_USER_NAME IN VARCHAR2,P_PASSWORD IN VARCHAR,P_TABLE_NAME OUT VARCHAR2,P_SCRIPT OUT VARCHAR2)
IS
chk_username all_users.username%type;
CURSOR C IS SELECT table_name FROM USER_TABLES;
t_tablename user_tables.table_name%type;
BEGIN
SELECT username into chk_username from all_users
where chk_username=p_user_name;
open c;
loop
fetch c into t_tablename;
exit when c% notfound;
end loop;
exception when no_data_found then
dbms_output.put_line('Wrong Username Or Password');
close c;
end;
/
Try this code. Let me know if this helps.
CREATE OR REPLACE PROCEDURE TABLE_INFO(
P_USER_NAME IN VARCHAR2,
-- P_PASSWORD IN VARCHAR, --Not required
P_TABLE_NAME OUT sys_refcursor)
-- P_SCRIPT OUT VARCHAR2) --Not required
AS
BEGIN
-----------------------For DDL script use dbms_metadata.get_ddl-------------------------
OPEN P_TABLE_NAME FOR
SELECT OWNER,TABLE_NAME,dbms_metadata.get_ddl('TABLE',TABLE_NAME) "table DDL"
FROM all_tables WHERE upper(OWNER) = upper(P_USER_NAME);
END;
--------------------To EXECUTE this proc---------------------------------
var usr VARCHAR2(100);
VAR p_lst refcursor;
exec TABLE_INFO(<username>,:p_lst);
------------------------------------------------------------------------
Check this out. This is a function returning all the values as per requirement.
-- Obj Creation
CREATE OR REPLACE TYPE my_obj
IS
OBJECT
(
TAB_NAME VARCHAR2(100),
DDL_S VARCHAR2(32676) );
-- Table type Creation
CREATE OR REPLACE TYPE my_tab
IS
TABLE OF my_obj;
--Function Creation---
CREATE OR REPLACE FUNCTION TABLE_INFO_FUN(
P_USER_NAME IN VARCHAR2 )
RETURN my_tab
AS
my_otpt my_tab;
BEGIN
-----------------------For DDL script use dbms_metadata.get_ddl-------------------------
SELECT CAST( multiset
(SELECT my_obj(TABLE_NAME,dbms_metadata.get_ddl('TABLE',TABLE_NAME))
FROM all_tables
WHERE upper(OWNER) = upper(P_USER_NAME)
) AS my_tab )
INTO my_otpt
FROM DUAL;
RETURN my_otpt;
END;
-- Using Function to Select Data -------------
SELECT * FROM TABLE(TABLE_INFO_FUN(<USERNAME>));
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;
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;