Weak REF CURSOR: discarding records?
Hi,
I'd like to discard the first N records from a weak REF CURSOR without having to specify the structure of the cursor. Is this possible?
For example:
LOOP
FETCH results INTO garbagecan
EXIT WHEN results%NOTFOUND;
END LOOP;
It seems that FETCH statement requires INTO to be specified with the correct structure.
-Jerome
null
it is not possible to fetch into some variable, which doesn't match the structure of the cursor variable.....
There is one way.....you can discard the first n records while assigning the query to cursor variable....
Frame ur query that ur going to assocaite to the cursor in the following way....
select * from (select rownum a, test.* from test) where a > N
where 'N' is the no of records that u don't want to be in the cursor.....
if u have doubt in this approach get back to me...
Similar Messages
-
I want to implement a stored procedure which takes a
weak ref cursor as one of its IN parameters. In the body
of the SP I want to analyze the "structure" of the weak
ref cursor: column names and types.
Any hints how to do this in PL/SQL?? Of course, in C via OCI
describing a (weak) ref cursor at run-time is no problem at
all.
Tobias.it is not possible to fetch into some variable, which doesn't match the structure of the cursor variable.....
There is one way.....you can discard the first n records while assigning the query to cursor variable....
Frame ur query that ur going to assocaite to the cursor in the following way....
select * from (select rownum a, test.* from test) where a > N
where 'N' is the no of records that u don't want to be in the cursor.....
if u have doubt in this approach get back to me... -
This is the first time I have a need at work to use a REF CURSOR type of the weak variety. After reading documentation
in SF's 'bible' Oracle PL/SQL Programming, I did everything right. Here's the code snippet:
-- TYPES
TYPE content_ID_curtype IS
REF CURSOR;
-- VARIABLES
c_SEARCH_STRING CONSTANT VARCHAR2(12) := 'v_content_id';
content_ID_cur content_ID_curtype;
v_content_ID am_content_content.content_ID%TYPE;
BEGIN
cache_sql_rec.sql_stmt := REPLACE(cache_sql_rec.sql_stmt, c_SEARCH_STRING, template_name_rec.content_ID);
OPEN content_ID_cur FOR cache_sql_rec.sql_stmt;
LOOP
FETCH content_ID_cur
INTO v_content_ID;
EXIT WHEN content_ID_cur%NOTFOUND;
END LOOP;
CLOSE content_ID_cur;
END;
Now the error I get is.... ORA-00911: invalid character When I used DBMS_OUTPUT to see the actual value of
"cache_sql_rec.sql_stmt", the SQL query looks fine. Even when I hardcoded the sql statement after the FOR keyword, it
worked fine. It's only when I use a variable to hold the whole SQL statement does it fail. Here's one value for the
variable cache_sql_rec.sql_stmt:
SELECT b.content_id
FROM am_content_mofcollection a,
am_content_collection b
WHERE a.content_id = 149090
AND a.collection_id = b.collection_id;
Basically I replace the string with an actual content_ID. Now content_ID is of type NUMBER(12) as is the variable
v_content_ID declared so that I FETCH INTO that variable, but the problem is, is that the exception gets raised during
the OPEN...cursor...FOR....sql_statement command.
Any thoughts on this bug?
Thanks,
Gio
Giovanni Jaramillo
Senior Software Engineer
Oracle Database Group
Amplified Holdings, Inc.
5750 Wilshire Blvd., Ste 501
Los Angeles, CA 90036-3638
(323)-556-8792
[email protected] http://www.amplified.comYes it turns out that the data had a semicolon at the end since it's being inserted by someone else. I know when executing DDL or DML statements via NDS you omit the semicolon. But didn't know it applied to REF CURSORS.
Also I added a colon to the variable that I was REPLACING since it can act as a bind variable.
Thanks Andrew.
Gio
null -
How can I iterate over the columns of a REF CURSOR?
I have the following situation:
DECLARE
text VARCHAR2 (100) := '';
TYPE gen_cursor is ref cursor;
c_gen gen_cursor;
CURSOR c_tmp
IS
SELECT *
FROM CROSS_TBL
ORDER BY sn;
BEGIN
FOR tmp IN c_tmp
LOOP
text := 'select * from ' || tmp.table_name || ' where seqnum = ' || tmp.sn;
OPEN c_gen FOR text;
-- here I want to iterate over the columns of c_gen
-- c_gen will have different number of columns every time,
-- because we select from a different table
-- I have more than 500 tables, so I cannot define strong REF CURSOR types!
-- I need something like
l := c_gen.columns.length;
for c in c_gen.columns[1]..c_gen.columns[l]
LOOP
-- do something with the column value
END LOOP;
END LOOP;
END;As you can see from the comments in the code, I couln'd find any examples on the internet with weak REF CURSORS and selecting from many tables.
What I found was:
CREATE PACKAGE admin_data AS
TYPE gencurtyp IS REF CURSOR;
PROCEDURE open_cv (generic_cv IN OUT gencurtyp, choice INT);
END admin_data;
CREATE PACKAGE BODY admin_data AS
PROCEDURE open_cv (generic_cv IN OUT gencurtyp, choice INT) IS
BEGIN
IF choice = 1 THEN
OPEN generic_cv FOR SELECT * FROM employees;
ELSIF choice = 2 THEN
OPEN generic_cv FOR SELECT * FROM departments;
ELSIF choice = 3 THEN
OPEN generic_cv FOR SELECT * FROM jobs;
END IF;
END;
END admin_data;
/But they have only 3 tables here and I have like 500. What can I do here?
Thanks in advance for any help!The issue here is that you don't know your columns at design time (which is generally considered bad design practice anyway).
In 10g or before, you would have to use the DBMS_SQL package to be able to iterate over each of the columns that are parsed from the query... e.g.
CREATE OR REPLACE PROCEDURE run_query(p_sql IN VARCHAR2) IS
v_v_val VARCHAR2(4000);
v_n_val NUMBER;
v_d_val DATE;
v_ret NUMBER;
c NUMBER;
d NUMBER;
col_cnt INTEGER;
f BOOLEAN;
rec_tab DBMS_SQL.DESC_TAB;
col_num NUMBER;
v_rowcount NUMBER := 0;
BEGIN
-- create a cursor
c := DBMS_SQL.OPEN_CURSOR;
-- parse the SQL statement into the cursor
DBMS_SQL.PARSE(c, p_sql, DBMS_SQL.NATIVE);
-- execute the cursor
d := DBMS_SQL.EXECUTE(c);
-- Describe the columns returned by the SQL statement
DBMS_SQL.DESCRIBE_COLUMNS(c, col_cnt, rec_tab);
-- Bind local return variables to the various columns based on their types
FOR j in 1..col_cnt
LOOP
CASE rec_tab(j).col_type
WHEN 1 THEN DBMS_SQL.DEFINE_COLUMN(c,j,v_v_val,2000); -- Varchar2
WHEN 2 THEN DBMS_SQL.DEFINE_COLUMN(c,j,v_n_val); -- Number
WHEN 12 THEN DBMS_SQL.DEFINE_COLUMN(c,j,v_d_val); -- Date
ELSE
DBMS_SQL.DEFINE_COLUMN(c,j,v_v_val,2000); -- Any other type return as varchar2
END CASE;
END LOOP;
-- Display what columns are being returned...
DBMS_OUTPUT.PUT_LINE('-- Columns --');
FOR j in 1..col_cnt
LOOP
DBMS_OUTPUT.PUT_LINE(rec_tab(j).col_name||' - '||case rec_tab(j).col_type when 1 then 'VARCHAR2'
when 2 then 'NUMBER'
when 12 then 'DATE'
else 'Other' end);
END LOOP;
DBMS_OUTPUT.PUT_LINE('-------------');
-- This part outputs the DATA
LOOP
-- Fetch a row of data through the cursor
v_ret := DBMS_SQL.FETCH_ROWS(c);
-- Exit when no more rows
EXIT WHEN v_ret = 0;
v_rowcount := v_rowcount + 1;
DBMS_OUTPUT.PUT_LINE('Row: '||v_rowcount);
DBMS_OUTPUT.PUT_LINE('--------------');
-- Fetch the value of each column from the row
FOR j in 1..col_cnt
LOOP
-- Fetch each column into the correct data type based on the description of the column
CASE rec_tab(j).col_type
WHEN 1 THEN DBMS_SQL.COLUMN_VALUE(c,j,v_v_val);
DBMS_OUTPUT.PUT_LINE(rec_tab(j).col_name||' : '||v_v_val);
WHEN 2 THEN DBMS_SQL.COLUMN_VALUE(c,j,v_n_val);
DBMS_OUTPUT.PUT_LINE(rec_tab(j).col_name||' : '||v_n_val);
WHEN 12 THEN DBMS_SQL.COLUMN_VALUE(c,j,v_d_val);
DBMS_OUTPUT.PUT_LINE(rec_tab(j).col_name||' : '||to_char(v_d_val,'DD/MM/YYYY HH24:MI:SS'));
ELSE
DBMS_SQL.COLUMN_VALUE(c,j,v_v_val);
DBMS_OUTPUT.PUT_LINE(rec_tab(j).col_name||' : '||v_v_val);
END CASE;
END LOOP;
DBMS_OUTPUT.PUT_LINE('--------------');
END LOOP;
-- Close the cursor now we have finished with it
DBMS_SQL.CLOSE_CURSOR(c);
END;
SQL> exec run_query('select empno, ename, deptno, sal from emp where deptno = 10');
-- Columns --
EMPNO - NUMBER
ENAME - VARCHAR2
DEPTNO - NUMBER
SAL - NUMBER
Row: 1
EMPNO : 7782
ENAME : CLARK
DEPTNO : 10
SAL : 2450
Row: 2
EMPNO : 7839
ENAME : KING
DEPTNO : 10
SAL : 5000
Row: 3
EMPNO : 7934
ENAME : MILLER
DEPTNO : 10
SAL : 1300
PL/SQL procedure successfully completed.
SQL> exec run_query('select * from emp where deptno = 10');
-- Columns --
EMPNO - NUMBER
ENAME - VARCHAR2
JOB - VARCHAR2
MGR - NUMBER
HIREDATE - DATE
SAL - NUMBER
COMM - NUMBER
DEPTNO - NUMBER
Row: 1
EMPNO : 7782
ENAME : CLARK
JOB : MANAGER
MGR : 7839
HIREDATE : 09/06/1981 00:00:00
SAL : 2450
COMM :
DEPTNO : 10
Row: 2
EMPNO : 7839
ENAME : KING
JOB : PRESIDENT
MGR :
HIREDATE : 17/11/1981 00:00:00
SAL : 5000
COMM :
DEPTNO : 10
Row: 3
EMPNO : 7934
ENAME : MILLER
JOB : CLERK
MGR : 7782
HIREDATE : 23/01/1982 00:00:00
SAL : 1300
COMM :
DEPTNO : 10
PL/SQL procedure successfully completed.
SQL> exec run_query('select * from dept where deptno = 10');
-- Columns --
DEPTNO - NUMBER
DNAME - VARCHAR2
LOC - VARCHAR2
Row: 1
DEPTNO : 10
DNAME : ACCOUNTING
LOC : NEW YORK
PL/SQL procedure successfully completed.
SQL>From 11g onwards, you can create your query as a REF_CURSOR, but then you would still have to use the DBMS_SQL package with it's new functions to turn the refcursor into a dbms_sql cursor so that you can then describe the columns in the same way.
http://technology.amis.nl/blog/2332/oracle-11g-describing-a-refcursor
Welcome to the issues that are common when you start to attempt to create dynamic code. If your design isn't specific then your code can't be either and you end up creating more work in the coding whilst reducing the work in the design. ;) -
Is there a different way to open a cursor for a ref cursor procedure?
hello everybody
i have two cursors, cur_a and cur_b, declared somewhere else in my application.
These two cursors have the same fields, in the same order, and i have to treat both in the same way. So i wrote a routine that gets as input a ref cursor based on the cur_a rowtype, and i am trying to use this routine for both.
The problem is that i am not able to open outside the routine the cursor in a different way than usual...
the common method is :
declare curs ref cursor ...
begin
open curs for (select *...)
end;
instead i would like to obtain something different
declare curs ref cursor ...
begin
open curs for cur_a
end;hi
thanks for answering
i wanted just to give a better idea, anyway you were near to get it.
the only difference is that the two cursors are not written in dynamic sql, just like strings, but are real cursors.
anyway, this is the version of the package i need, but i am not able to compile
(your original code is commented and immediately below there is my code)
CREATE OR REPLACE PACKAGE BODY mytest
IS
--cur_a VARCHAR2(200) := 'SELECT dummy FROM DUAL';
CURSOR cur_a
IS
SELECT dummy
FROM DUAL;
--cur_b VARCHAR2(200) := 'SELECT ''fred'' FROM DUAL';
CURSOR cur_b
IS
SELECT 'fred' fred
FROM DUAL;
TYPE t_cur_a IS REF CURSOR
RETURN cur_a%ROWTYPE
--PROCEDURE routine_a_b (p_cur SYS_REFCURSOR) IS
PROCEDURE routine_a_b (p_cur t_cur_a)
IS
v_x VARCHAR2 (10);
BEGIN
LOOP
FETCH p_cur
INTO v_x;
EXIT WHEN p_cur%NOTFOUND;
DBMS_OUTPUT.put_line (v_x);
END LOOP;
END;
PROCEDURE doit
IS
--v_curs SYS_REFCURSOR;
v_curs t_cur_a;
BEGIN
NULL;
-- open v_curs FOR cur_a;
OPEN v_curs FOR cur_a;
routine_a_b (v_curs);
CLOSE v_curs;
-- open v_curs FOR cur_b;
-- routine_a_b(v_curs);
-- close v_curs;
END;
END;
the error is:
cursor 'V_CURS' cannot be used in dynamic SQL OPEN statement
i did read that if use weak ref cursor, it could work, so i declare the ref cursor type in this way:
TYPE t_cur_a IS REF CURSOR;
instead than
TYPE t_cur_a IS REF CURSOR
RETURN cur_a%ROWTYPE
what i get is another error (in the open cursor command)
PLS-00382: expression is of wrong type....
but if i replace
OPEN v_curs FOR cur_a;
with
OPEN v_curs for select dummy from dual;
it works... but i already knew it.. :-)
anyway, i used a work around to resolve it, so it's just philosophy -
Dispalying output from a REF CURSOR
Friends,
I'm getting my self into indepth pl/sql and need some help from you to clear some basic concepts.
create table MASTER_TABLE
street_info varchar2(100),
property_type varchar2(50) ------- i.e values here would be 'HOME_TABLE' ,'COM_PROP_TABLE' etc
create table HOME_TABLE
property_id char(5),
prop_desc varchar2(100),
cost varchar2(10),
location varchar2(100)
create table COM_PROP_TABLE
property_id char(5),
prop_desc varchar2(100),
cost varchar2(10),
location varchar2(100)
I want to use a single procedure to open a weak REF CURSOR variable for the appropriate table based on the street address and display all information from that table.
Here is what I want to to - execute a stored procedure which accepts 1 'in' paramter and 1 'in out ' parameter.
IN paramter - accepts street address
IN OUT paramter - depending on address , if it is related to 'Homes' , it should display all information from the HOME Table, else it will display information from the 'Commerical Property' table.
create or replace package pack_address_info as
type v_info_type ref cursor;
end pack_address_info;
create or replace procedure schema.sp_home_info(v_add in varchar2,v_show in out v_info_type)
is
home_type constant integer :=1;
commercial_type constant integer :=2;
cursor show_data_cur is
select property_type from MASTER TABLE where street_info=v_add;
var_cursor show_data_cur%rowtype;
begin
open show_data_cur;
fetch show_data_cur into var_cursor;
close show_data_cur;
if var_cursor.property_type= HOME_TABLE
then
open v_show for
select * from HOME_TABLE where location=v_add;
elseif var_cursor.table_name = COM_PROP_TABLE
then
open v_show for
select * from COM_PROP_TABLE where location=v_add;
end if;
end schema.sp_home_info;
I can create the package and the stored proc ... but then ???? i'm stuck ;(
Now , i don't know how to display the output from the HOME TABLE or the COM_PROP_TABLE depending on what the address is entered? Is this code correct. Can you please help me modify this code so that I can achieve my objective.
This is an example from the book 'Oracle PL/SQL Programming, 4th Edition' under the 'CURSOR' section - 15.6
Thanks for the help in advance.Here is one sample ->
satyaki>
satyaki>select * from v$version;
BANNER
Oracle Database 10g Enterprise Edition Release 10.2.0.3.0 - Prod
PL/SQL Release 10.2.0.3.0 - Production
CORE 10.2.0.3.0 Production
TNS for 32-bit Windows: Version 10.2.0.3.0 - Production
NLSRTL Version 10.2.0.3.0 - Production
Elapsed: 00:00:00.02
satyaki>
satyaki>
satyaki>CREATE OR REPLACE PACKAGE aaa_sat
2 AS
3 TYPE crs IS REF CURSOR RETURN emp%ROWTYPE;
4 FUNCTION fc_retcur (e_no IN NUMBER)
5 RETURN crs;
6 END aaa_sat;
7 /
Package created.
Elapsed: 00:00:01.03
satyaki>
satyaki>
satyaki>CREATE OR REPLACE PACKAGE BODY aaa_sat
2 AS
3 FUNCTION fc_retcur (e_no IN NUMBER)
4 RETURN crs
5 IS
6 l_crs crs;
7 BEGIN
8 OPEN l_crs FOR
9 SELECT * FROM emp
10 WHERE empno = e_no;
11
12 RETURN l_crs;
13 END;
14 END aaa_sat;
15 /
Package body created.
Elapsed: 00:00:00.18
satyaki>
satyaki>
satyaki>DECLARE
2 l_emp_rec emp%ROWTYPE;
3 l_crs aaa_sat.crs;
4 BEGIN
5 l_crs := aaa_sat.fc_retcur (7782);
6 LOOP
7 FETCH l_crs
8 INTO l_emp_rec;
9 EXIT WHEN l_crs%NOTFOUND;
10 DBMS_OUTPUT.put_line (l_emp_rec.ename);
11 END LOOP;
12 CLOSE l_crs;
13 END;
14 /
CLARK
PL/SQL procedure successfully completed.
Elapsed: 00:00:00.40
satyaki>
satyaki>Got Me?
Regards.
Satyaki De. -
I have a stored procedure that returns a weak REF CURSOR as an out parameter. I want to access the rows that are returned, in an OCI application. I want a sample OCI program that does this. The PL/SQL code is as follows
PACKAGE TEST_PACKAGE AS
TYPE RCT IS REF CURSOR;
END;
PROCEDURE TEST_PROCEDURE (R OUT TEST_PACKAGE.RCT)
AS
BEGIN
OPEN r FOR
SELECT * FROM XXX;
END;
THANKS.Hello,
I used in my application regular connections, I created
CallableStatement with these connections, later I got one cursor with:
mr = ((OracleCallableStatement)cstmt).getCursor(1)
where mr is ResultSet and cstmt is CallableStatement.
But, when I use the Commerce PoolConnection I get serialConnection
and it creates serialCallableStatement and the command:
mr = ((OracleCallableStatement)cstmt).getCursor(1)
get the next exception:
java.lang.ClassCastException:
weblogic.jdbc20.rmi.SerialCallableStatement at......
Are you working with Bea ConnectionPool
or regular Connections?
Thank you.
<BLOCKQUOTE><font size="1" face="Verdana, Arial">quote:</font><HR>Originally posted by Matt Sivertson ([email protected]):
I'm having a very strange problem with some JDBC code. Basically, there is a StoredProcedure in the DB that we call through JDBC. One of the out parameters is a REF CURSOR. My user does not have select access to the table, but the stored procedure does. When I try and get the ResultSet corresponding to that RefCursor using the OracleCallableStatement.getCursor() method, and exception gets thrown saying it cannot find the table. We checked on the database, and it is actually performing a new select statement as My user, rather than as the StoredProcedure. If we open up the permissions on the table, everything works fine, but this defeats the whole purpose of what the DBA wants.
BTW, this same Stored Procedure works when fine when accesed through PL/SQL or SQL+. Only JDBC seems to have a problem with it. Any help is greatly appreciated.
Matt Sivertson
[email protected]<HR></BLOCKQUOTE>
null -
Stored procedure and ref cursor problem
I am trying to create a stored procedure that can be used in Crystal Reports. To do this I have to create a package and a ref cursor. My SQL is below:
--Package
Create or Replace Package Test_Package
as type test_type is ref cursor;
end;
--Procedure
Create or Replace Procedure Test_Proc
(test_cursor in out test_package.test_type,
parameter in string
as
begin
open test_cursor for
select ClientName from apbpman.cv_client where clientref = parameter;
end;
--When trying to execute the SP in Oracle I use:-
set serveroutput on
declare
test_cursor apbpman.test_package.test_type;
resultset test_cursor%rowtype;
begin
apbpman.test_proc(test_cursor,'0096');
if not test_cursor%isopen then
dbms_output.put_line ('OK');
else
dbms_output.put_line ('Not OK');
end if;
fetch test_cursor into resultset;
while test_cursor%found loop
dbms_output.put_line(resultset.ClientName);
fetch test_cursor into resultset;
end loop;
end;
Whenever this runs I receive the following error reports:
resultset test_cursor%rowtype;
ERROR at line 3:
ORA-06550: line 3, column 13:
PLS-00320: the declaration of the type of this expression is incomplete or malformed
ORA-06550: line 3, column 13:
PL/SQL: Item ignored
ORA-06550: line 11, column 25:
PLS-00320: the declaration of the type of this expression is incomplete or malformed
ORA-06550: line 11, column 2:
PL/SQL: SQL Statement ignored
ORA-06550: line 13, column 24:
PLS-00320: the declaration of the type of this expression is incomplete or malformed
ORA-06550: line 13, column 3:
PL/SQL: Statement ignored
ORA-06550: line 14, column 26:
PLS-00320: the declaration of the type of this expression is incomplete or malformed
ORA-06550: line 14, column 3:
PL/SQL: SQL Statement ignored
I have tried in vain to find a resolution to this but have failed. Please help.
Thanks,
PaulUnless you are running a really old version of Oracle, any weak ref cursor can just be declared SYS_REFCURSOR. Also, you can't use a weak ref cursor for %ROWTYPE. You can test the procedure in SQL*Plus by using it to populate a refcursor variable.
-
Example of Simple SP using REF Cursors
Hi All,
i want simple stored procedure using REF Cursors.
Select * From Emp Where Deptno='20'
Use Scott & Tiger, Default database.
i am poassing parameter deptno at runtime.i want all the records of deptno=20.
i know REF Cursors return Record Set.but i created,it will throw errors.
Anyone pls helpPost your code what you have tried. Also your requirement can be fulfilled with parametrized cursor.
http://download.oracle.com/docs/cd/E11882_01/appdev.112/e17126/static.htm#LNPLS00602
http://download.oracle.com/docs/cd/E11882_01/appdev.112/e17126/static.htm#LNPLS00605 -
Ref cursor vs sys_refcursor
What is the diffeerenece between ref cursor and sys_refcursor.in which scenarios we use ref cusor and sys_refcursor with example.For the performace point of view which is better.
BluShadow wrote:
SAMBIT RAY wrote:
Hi,
thanks for use ful difference.
i got your difference between two but as per performace level which is better.plz suggestAs billy said they are all cursors.
As my link highlights, a ref cursor of any sort is just a pointer to a query.
SYS_REFCURSOR is just a synonym for the REF CURSOR type.
There is no performance difference.Putting on my nit picking hat :-)
Sys_refcursor is a named type of type refcursor. The $ORACLE_HOME/rdbms/admin/stdspec.sql ther is this line:
/* Adding a generic weak ref cursor type */
type sys_refcursor is ref cursor;Since it is in package standard we can use it without qualifying it with a package name, but
declare
l_cur sys_refcursor;is exactly the same as:
reate package my_pack as
type john_cursor is ref cursor;
end;
declare
l_cur my_pack.john_cursor;Taking off my nit picking hat now.
John -
Cursor difference (REF Cursor & Sys_Refcursor)
Hi,
Is there any difference between REF Cursor and SYS_Refcursor?
I see some packages using sys_refcursor and some using REF Cursor.
Package 1 (Spec):
PROCEDURE s_demo1 (
ret_rset OUT sys_refcursor
Package 2 (Spec):
TYPE cur_set IS REF CURSOR;
PROCEDURE s_test1 (out_data OUT cur_set);
PROCEDURE s_test2 (out_data OUT cur_set);I am going through this link (http://sql-plsql.blogspot.com/2007/05/oracle-plsql-ref-cursors.html) but didn't find the answer.DomBrooks wrote:
John - don't get me wrong, I'm not suggesting that as soon as something like SYS_REFCURSOR comes along, everything should get rewritten. It's just I still see new packages written on 11g by, say mainly C# or java developers, which use this old style.
But.... are you saying that you can't do this?
CREATE OR REPLACE PACKAGE old_package AS
TYPE pkg_cur IS REF CURSOR;
FUNCTION foo(p_id IN NUMBER) RETURN sys_refcursor;
END;
CREATE OR REPLACE PACKAGE BODY old_package AS
FUNCTION foo(p_id IN NUMBER) RETURN sys_refcursor IS
l_cur sys_refcursor;
BEGIN
OPEN l_CUR FOR SELECT * FROM dual WHERE 1 = p_id;
RETURN l_cur;
END;
END;
Absolutely, I can even declare pkg_cursor as a sys_refcursor and all of the old calls will still work since sys_refcursor is just a ref cursor in disguise. What I cannot do is drop the declaration in the package spec since the outside callers rely on it, so since sys_refcusor is just a ref cursor in disguise, why use it?
In fact, in OHOME/rdbms/admin/stdspec.sql which is the declarations for the package standard sys_refcursor is declared as:
/* Adding a generic weak ref cursor type */
type sys_refcursor is ref cursor;Since things declared in standard package (like data types, operators, all of the named exceptions etc.) are "globally" available without using the package name, sys_refcursor just provides a method to save a few keystrokes everywhere. It is no different functionally than a package declared ref cursor. The main difference is that you cannot create a strongly typed sys_refcursor, if you want/need one, you need to use a ref cursor.
I do tend to use sys_refcursor in new code, but it took me a while to switch because there is not much real benefit as far as I can see.
John
Edited by: John Spencer on Nov 17, 2010 4:11 PM -
Hi
I wanted to take count of ref cursors return records.
I have added OUT parameter for procedure and i m returning records from this OUT parameter,
so i wanted to check count of record before returning it from procedure.
please do the needful.also
there is no way way to find out how many records at all will be retrieved in a cursor BEFORE you fetch the very last row from it. Cursor_name%rowcount gives the number of rows selected so far and that count increments every time you fetch.
You use %rowcount only with implicit cursors that do insert/update/delete. -
Create record variable that refers dynamic query assigned to a ref cursor?
Hi ,
Just explaining what I am trying to achieve:
1) i have a hr.departments table that was loaded in hr schema on 1st oct 2012 with 4 columns(department_id, department_name, manager_id, location_id)
2) now I have a new schema by my name 'rahul' and I have loaded departments table but now an additional column has come into picture,ie created_date, this table got loaded on 1st-Nov-2012
3) Now going forward my columns could be dropped from the departments table (it can be a case), for example might be my departments table in my schema 'rahul' one day could comprise of only 3 columns(department_id,department_name,manager_id)
4) Now in the next step, I have managed to extract common column names(in a single line where columns are delimited using a comma) from both the tables(hr.departments and rahul.departments) which are (department_id, department_name, manager_id, location_id) using all_tab_cols table and I have written a function for it which i will be pasting below.
5) now going forward, using the above column names line with column names delimited using comma, I have used a ref cursor and assigned a query to it using the line of columns that I have extracted from the above point
6) Now I want to create a record variable which refers to my ref cursor, something like we do when we create a record variable by reffering to an explicit cursor defination that we give in the declaration block.
PS:
1) I have been out of touch with plsql for a long time so I have lost a lot of mmeory regarding plsql.
2) basically I need to compare data in hr.departments table with rahul.departments table for only columns that are common to both the tables, rest new or discarded columns information will go in one of the log tables that I have created(this is done already)
Please help me, I did try searching on google for the same but it really confused me very badly, any kind of help is appreciated, please find my code below:
Regards
Rahul
Code :
===================================================================================================
create or replace procedure p_compare_data(fp_old_table_name in varchar2, fp_new_table_name in varchar2)
is
type ref_cursor_old_table is ref cursor;
v_ref_cursor_old_table ref_cursor_old_table;
--record_v_ref_cursor_old_table v_ref_cursor_old_table;
--record_ref_cursor_old_table v_ref_cursor_old_table%ROWTYPE;
Lv_all_column_names varchar2(2000);
function f_fetch_common_column_names(fp_old_table_name in varchar2, fp_new_table_name in varchar2)
return varchar2
is
Lv_all_column_names varchar2(2000);
begin
execute immediate 'select ltrim(all_column_names,'','') all_column_names_in_line from (select * from (select sys_connect_by_path(hr_e_column_name,'','') all_column_names from (select hr_e_column_name, rownum curr, rownum - 1 prev from (select hr_e.* , rahul_e.* , case when (hr_e_column_name = rahul_e_column_name) then 1 when (rahul_e_column_name is NULL) then 2 when (hr_e_column_name is NULL) then 3 end decision from (select column_name hr_e_column_name from all_tab_cols where owner ='''||substr(fp_old_table_name,1,instr(fp_old_table_name,'.',1,1)-1)||''' and table_name = '''||substr(fp_old_table_name,instr(fp_old_table_name,'.',1,1)+1)||''') hr_e full outer join (select column_name rahul_e_column_name from all_tab_cols where owner = '''||substr(fp_new_table_name,1,instr(fp_new_table_name,'.',1,1)-1)||''' and table_name = '''||substr(fp_new_table_name,instr(fp_new_table_name,'.',1,1)+1)||''') rahul_e on hr_e.hr_e_column_name = rahul_e.rahul_e_column_name) decision_table where decision = 1) a start with a.curr = 1 connect by prior curr = prev) b order by length(b.all_column_names) desc) all_column_names_in_line where rownum = 1' into Lv_all_column_names;
return (Lv_all_column_names);
end;
begin
Lv_all_column_names := f_fetch_common_column_names(fp_old_table_name, fp_new_table_name);
--dbms_output.put_line(Lv_all_column_names);
open v_ref_cursor_old_table for ('select '||Lv_all_column_names||' from '||fp_old_table_name);
end;
=====================================================================================================>
6) Now I want to create a record variable which refers to my ref cursor, something like we do when we create a record variable by reffering to an explicit cursor defination that we give in the declaration block.
>
This thread is basically nothing more than a continuation of your original thread except now you are finally explaining what you are really trying to do.
Re: passing table name to a procedure and then need to open a cursor ..
In that original thread you said you found the solution
>
Well Mate thanks for your suggestion but I got it working through ref cusror, thanks for your time.
>
So I ask you to post your 'solution' and when you finally did it was clear that you hadn't solved anything at all. Your solution used a ref cursor all right but the code relied on a record ('record_employees') that was based on a table name ('employees') that was declared within the procedure. There isn't much point in passing in a table name if you have to hard-code the table name in the procedure.
create or replace procedure p_ref_cursor(fp_old_table in varchar2)
is
type ref_cursor is REF CURSOR;
v_ref_cursor ref_cursor;
record_employees hr.employees%ROWTYPE;
begin
open v_ref_cursor for 'select * from '||fp_old_table;
loop
fetch v_ref_cursor into record_employees;
exit when v_ref_cursor%NOTFOUND;
dbms_output.put_line(record_employees.employee_id);
end loop;
end;Then sb92075 ask you the question that illustrates what I just said
>
what happens when you pass in "HR.DEPARTMENTS" ; besides throwing errors?
>
And you blew him off with this
>
Mate, departments never came in my context, in my prior message I explained what I was trying to achieve ... so I dont know what problem you are understanding reading my posts.
>
And now here you are asking how to get this to work for the departments table.
It is very difficult to help someone that won't tell us what it is they are really trying to do so we can try to suggest some better ways of doing it. Hopefully, in the future, you wil start by explaining your problems instead of focusing on the solution you think you should use.
Back to the issue -
The first thing you should do is finish defining the requirements. Assuming the above actually works to identify columns that have different data what are you going to do with that information?
1. Do you need to save that different data from TABLE1 somewhere?
2. If you don't save it how will anyone look at it to decide which table has the correct data?
3. If you do save it how will you save it 'generically' since other tables will have different columns and datatypes?
4. What about the data from the same record in TABLE2; do you need to save that data somewhere?
5. Will these two tables have primary keys? Are they on the same columns in each table? If not what if TABLE1 has one record but there are TWO records in TABLE2 that are identical. Is that a match? Or is that a problem because TABLE2 has an extra record even though the record is identical?
In short detecting the differences is just one small part of the entire problem. You also need to save those differences somewhere so someone can examine the data and decide what action to take. That is the more difficult part of trying to implement a 'generic' solution.
But now that we know what you are really trying to do take a read through this thread from 6 years ago. It has three different ways to pass a query to a procedure and get different output. You may want to save a copy of the thread since it has some very advanced techniques in it.
How to pipeline a function with a dynamic number of columns?
See ascheffer's reply Posted: May 9, 2006 4:53 AM for using data cartridge functionality with a pipelined function.
See Kamal's reply Posted: May 10, 2006 4:49 AM - it shows how to get XML output.
See BluShadow's reply Posted: Mar 27, 2009 1:50 AM - for using dynamic sql -
DB proc - do you need to create a table to pass a ref cursor record type?
I want to pass a limited selection of columns from a large table through a DB procedure using a REF CURSOR, returning a table rowtype:
CREATE OR REPLACE package XXVDF_XPOS_DS021_ITEMS AS
TYPE XXVDF_XPOS_DS021_ITEM_ARRAY
IS REF CURSOR
return XXVDF_XPOS_DS021_ITEM_TABLE%ROWTYPE;
Do I need to create this dummy table?
I can't get a TYPE to work, where the type is an OBJECT with the desired columns in it.
So a dummy empty table will sit in the database...
Is there another way?
thanks!You can use RECORD type declaration:
SQL> declare
2 type rec_type is record (
3 ename emp.ename%type,
4 sal emp.sal%type
5 );
6 type rc is ref cursor return rec_type;
7 rc1 rc;
8 rec1 rec_type;
9 begin
10 open rc1 for select ename, sal from emp;
11 loop
12 fetch rc1 into rec1;
13 exit when rc1%notfound;
14 dbms_output.put_line(rec1.ename || ' ' || rec1.sal);
15 end loop;
16 close rc1;
17 end;
18 /
SMITH 800
ALLEN 1600
WARD 1250
JONES 2975
MARTIN 1250
BLAKE 2850
CLARK 2450
SCOTT 3000
KING 5000
TURNER 1500
ADAMS 1100
JAMES 950
FORD 3000
MILLER 1300or use, for example, VIEW to declare rowtype:
SQL> create view dummy_view as select ename, sal from emp;
View created.
SQL> declare
2 type rc is ref cursor return dummy_view%rowtype;
3 rc1 rc;
4 rec1 dummy_view%rowtype;
5 begin
6 open rc1 for select ename, sal from emp;
7 loop
8 fetch rc1 into rec1;
9 exit when rc1%notfound;
10 dbms_output.put_line(rec1.ename || ' ' || rec1.sal);
11 end loop;
12 close rc1;
13 end;
14 /
SMITH 800
ALLEN 1600
WARD 1250
JONES 2975
MARTIN 1250
BLAKE 2850
CLARK 2450
SCOTT 3000
KING 5000
TURNER 1500
ADAMS 1100
JAMES 950
FORD 3000
MILLER 1300 Rgds. -
Sorting records dynamically in REF cursor, based upon a dynamic field
Hi,
I have a REF CURSOR built by using row type, table type and PIPELINE function. I have opened the ref cursor now. I would like to update a field called 'RANK' based upon 'RATIO' field in the REF CURSOR. i.e order the records in the ref cursor by RATIO field and then update the RANK as 1, 2, 3, 4, ....
Aim: I want to update a field in the REF CURSOR based upon another numeric field.
Please help me.
OPEN sales FOR
SELECT RANK, ratio
FROM TABLE (fngetfundholdingsale (in_primarykey, in_flag));
loop
fetch sales into sale1;
exit when sales%notfound;
--I want to update sale1.rank based upon ratio
end loop;
Thanks
AshokTry to use NDS (Native Dynamic SQL):
l_order := 'ratio';
OPEN sales FOR
'SELECT rank' ||
' FROM TABLE (fngetfundholdingsale (:in_primarykey, :in_flag))' ||
' ORDER BY ' || l_order
USING in_primarykey, in_flag;Regards,
Zlatko
Maybe you are looking for
-
2011 MacBook Pro dead not turning on, how do I get all my files off it?
Hi, I have an early 2011 15" MacBook Pro. Basically it's completely died on me, a few things have been going wrong so I know it's times up. I just want to know how I can get all my photos, documents & files off if it's completely died & won't turn on
-
I know this is probably going to be for nothing since I doubt many people have been doing custom portfolios using flex yet but I have an extremely annoying problem I was hoping to get help with. I had to create my own version of the Revolve layout b
-
What's the correct way to use "Relocate Masters?"
I have 100GB of master images on one drive. Twenty gigs of those photos are imported into Aperture already (I use the referenced masters method), and I will be importing the remaining 80 gigs eventually (all referenced). For now I need to move all 10
-
Profile option to be set to view About this page link
Hi All, I am working in OAF 5.7h.Kan anyone tell me da name of the profile option that needs to be set for being able to view the About this page link in the footer of all pages. thanks in advance
-
Other Charges on total before discount value
Hi Experts, I faced an issue while generating sales quotation, apart from tax code we need to put other charges on the total before discount value of the documents like UT charges,P&F charges, Tarnsit Insurance and TPI Charges. However these other ch