DESCRIBING A REF CURSOR
For debugging purposes, I would like to be able to describe a REF CURSOR returned by a function in a package, using pl/sql.
Can you help me ?
ZlatKo
A brave attempt and well done for putting up with the forum software.
Alas, I can't catually run the code - I get the following error-stack. I'll have another go at it this lunchtime.
If I'm not mistaken your procedure would give us a visual output of the REF CURSOR structure, just like DESC. I think the original poster was after something they could use programmatically inside a PL/SQL procedure to interrogate and process a REF CURSOR with an unknown signature. It would be possible to walk the structure as you do, suck out the values and store them in arrays. Fine. But without knowing the column names how do we know what to do with these values?
At some point the receiving program has to know what the purpose of the REF CURSOR. We can imagine a function that generates a REF CURSOR from one of three queries depending upon the value of an input parameter. Every program which calls that function must pass in that parameter and therefore must know the signature of the REF CURSOR that it gets back.
The idea of a function returning data at its own whim is a bit laughable. Even web services, surely the ultimate expression of the encapsulation paradigm, insist on the publication of a signature - what we have to put in, what we will get back.
Cheers, APC
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... -
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. ;) -
How to update data returned using REF CURSOR
Hi all,
I am trying to update updated data in a gridview but the update button seem to do nothing as i retrieve data using REF CURSOR.
Let me describe the architecture of my application first. I'm trying to implement best practice whenever possible. I am following the data access tutorial published in www.asp.net , the only difference is that i have an Oracle (10g) database. So I split my application into three layers, data access, business logic, and presentation layer. I'm also writing all queries in an Oracle package.
So I have my Oracle packages that perform CRUD operations. Then I have an xsd file that define dataTable based on the package procedure. My business logic layer then calls functions defined in the xsd file. And finally a detailsView control that uses an ObjectDataSource to call business logic functions.
In a nutshell, I am just trying to update records retrieved using REF CURSOR. Your help is very much appreciated. Please let me know if further details are required. Cheers,In the DataSet (xsd) where your DataTable is defined, you just need to add additional methods to the TableAdapter to handle insert, update and delete, either with SQL or by mapping to stored procedures.
Alternatively in code, create an OracleDataAdapter and supply its InsertCommand, UpdateCommand and DeleteCommand.
David -
Ref cursors in Database adapter
Hi,
Is the database adapter capable of handling ref cursors as the datatype of the output parameters of a pl/sql procedure?
For instance if I have the following in my package-spec:
TYPE SomeRecordType IS RECORD
( record_pk mut_table.record_pk%TYPE
, person_nr person_table.person_nr%TYPE
, field_1 mut_table.field_1%type
, field_2 mut_table.field_2%type
, field_3 mut_table.field_3%type
TYPE SomeCursorType IS REF CURSOR RETURN SomeRecordType;
PROCEDURE read_records
( cursor_out OUT SomeCursorType
, exception_code OUT number
, exception_message OUT varchar2
Can the database adapter call the read_records procedure?
I've never seen this in any doc. I know it can't handle record types (that is in 10.1.2 it couldn't as far as I know). So I figure that the above is not possible.
Thanks in advance.
Regards,
MartienWe have successfully used a sys_refcursor OUT parameter for a database procedure call and which is used by a DBAdapter to return a single dataset.
At the time I remember attempting to use a strongly typed ref cursor as the parameter. I think this is what you are attempting to do. I rejected this approach at the time as I was not able to do this. It was, in our case, as simple as using the system defined ref cursor type (i.e. weakly typed).
The handling of the returned dataset was not immediately obvious, but can be handled by as fairly simple XSL transformation to a locally defined variable of the requisite xml structure. I won't describe in detail how to do it as it is specific to our process. Suffice to say the transformation loops over all result rows assign via a test to the correct result field in our local variable.
e.g.
<xsl:template match="/">
<ns1:BatchRequest004>
<xsl:for-each select="/db:OutputParameters/db:P_SCHSHP_REF_CUR/db:Row">
<ns1:statusRqst>
<xsl:if test='db:Column/@name = "ID"'>
<xsl:attribute name="id">
<xsl:value-of select="db:Column[1.0]"/>
</xsl:attribute>
</xsl:if>
</ns1:statusRqst>
</xsl:for-each>
</ns1:BatchRequest004>
HTH and that I haven't misidentified your problem. -
VC 7.0 Oracle stored procedures resultset with ref cursor
Can VC (we are on NW7 SP13) handle Oracle's datatype ref cursor - which is the standard solution in Oracle to return result sets - as the return value of a stored procedure?
When testing a data service in the VC story board based upon a simple Oracle function like:
create or replace package pkg_dev
is
type t_cursor is ref cursor;
end;
create or replace function vc_stub return pkg_dev.t_cursor
as
l_cursor pkg_dev.t_cursor;
begin
open l_cursor for select ename from emp;
return l_cursor;
end;
(just as example - I know that could be easily retrieved using the BI JDBC connector framework and accessing tables / views)
I am always running in the "portal request failed ( Could not execute Stored Procedure)" error - so I am not able to use the "add fields" function to bind the output.
The defaulttrace contains entries like:
Text: com.sap.portal.vc.HTMLBRunTime
[EXCEPTION]
com.sapportals.connector.execution.ExecutionException: Could not execute stored procedure
Caused by: java.sql.SQLException: Invalid column type
at oracle.jdbc.driver.DatabaseError.throwSqlException(DatabaseError.java:112)
We deployed Oracle's own jdbc-driver for Oracle 10g. Using that driver and a portal jdbc connector framework entry the stored procedures of the Oracle database user mapped to the portal user are discovered and available in the "Find Data Services" section.We deployed the drivers as described in the HowTo Papers (e.g.Hwo to Configure UD Connect on the J2EE Server for JDBC Access to External Databases). When deploying the drivers you assign a freely definable name for the set of Oracle's jar-files (eg. oracle_10) as library name. Having deployed the drivers in that way only System Definitions via BI JDBC connector framework were working. With a little help from SAP Support (call lasted more than 2 months till a very capable member of the support team made things working in a very short time) we got the portal jdbc connection with Oracle's jar-files working:
Here are instructions how to add reference:
1. Connect to the j2ee using telnet, e.g in the cmd window type:
telnet <host> <port> + 8, enter uid and pwd of j2ee admin.
2. jump 0
3. add deploy
4. change_ref -m com.sapportals.connectors.database <your lib name> <your lib name = oracle_10>
Trying to manually add this reference in visual admin connector container for JDBCFactory failed - reference could be added and saved, but then disappeared (at least in NW7 with SP12). Adding the reference as described above solved the problem. -
Version details
BANNER
Oracle Database 10g Enterprise Edition Release 10.2.0.4.0 - 64bi
PL/SQL Release 10.2.0.4.0 - Production
CORE 10.2.0.4.0 Production
TNS for Solaris: Version 10.2.0.4.0 - Production
NLSRTL Version 10.2.0.4.0 - ProductionBelow is the procedure where I'm using ref cursor
CREATE OR REPLACE PROCEDURE ref_sample
p_account_nbr in varchar2,
p_ref_out out sys_refcursor
IS
BEGIN
OPEN p_ref_out FOR
SELECT account_nbr,status,(
CASE
WHEN status = 'Pending' THEN
req_mail_date
WHEN status IN ('Rejected','Approved') THEN
NVL(verified_mail_date,req_mail_date)
END
)req_mail_date ,
CASE
WHEN status = 'Pending' THEN
NULL
WHEN status IN ('Rejected','Approved') THEN
NVL(verified_user_id,req_user_id)
END
)req_user_id
FROM X_tbl
WHERE account_nbr IN p_account_nbr
AND TRUNC(upload_date) = TRUNC(SYSDATE)
ORDER BY upload_date DESC ;
END;
/My input parameter p_account_nbr looks like ('a1','a2','a3')
Now,after knowing the importance of bind variables I'd like to make use of them in the above ref cursor.
But,here my input parameter is a string of varying length..either I've to go for the approach suggested here
http://asktom.oracle.com/pls/asktom/f?p=100:11:3667281145899708::::P11_QUESTION_ID:110612348061
or
http://www.dba-oracle.com/t_cursor_sharing.htm
I'm not much clear with the first approach,so I'm thinking of to modify my procedure as below
CREATE OR REPLACE PROCEDURE ref_sample
p_account_nbr in varchar2,
p_ref_out out sys_refcursor
IS
BEGIN
alter session set cursor_sharing=force;
OPEN p_ref_out FOR
SELECT account_nbr,status,(
CASE
WHEN status = 'Pending' THEN
req_mail_date
WHEN status IN ('Rejected','Approved') THEN
NVL(verified_mail_date,req_mail_date)
END
)req_mail_date ,
CASE
WHEN status = 'Pending' THEN
NULL
WHEN status IN ('Rejected','Approved') THEN
NVL(verified_user_id,req_user_id)
END
)req_user_id
FROM X_tbl
WHERE account_nbr IN p_account_nbr
AND TRUNC(upload_date) = TRUNC(SYSDATE)
ORDER BY upload_date DESC ;
alter session set cursor_sharing=exact;
END;
/Please let me know if the above modified code is fine or should I use bind variables??Also let me know better approach of both.The correct way to do this is use an array type for the input values as in this example.
SQL> create or replace procedure p
2 (
3 p_values sys.odcivarchar2list,
4 c out sys_refcursor
5 ) as
6 begin
7 open c for
8 select object_name, owner, object_type
9 from all_objects
10 where object_name in (select column_value from table(p_values));
11 end;
12 /
Procedure created.
SQL> var c refcursor
SQL> exec p (sys.odcivarchar2list('DUAL','USER_VIEWS'), :c)
PL/SQL procedure successfully completed.
SQL> print c
OBJECT_NAME OWNER OBJECT_TYPE
DUAL SYS TABLE
DUAL PUBLIC SYNONYM
USER_VIEWS SYS VIEW
USER_VIEWS PUBLIC SYNONYM
SQL> exec p (sys.odcivarchar2list('DUAL','USER_VIEWS','ALL_OBJECTS','ALL_SOURCE'), :c)
PL/SQL procedure successfully completed.
SQL> print c
OBJECT_NAME OWNER OBJECT_TYPE
DUAL SYS TABLE
DUAL PUBLIC SYNONYM
ALL_OBJECTS SYS VIEW
ALL_OBJECTS PUBLIC SYNONYM
USER_VIEWS SYS VIEW
USER_VIEWS PUBLIC SYNONYM
ALL_SOURCE SYS VIEW
ALL_SOURCE PUBLIC SYNONYM
8 rows selected.
SQL>That and other methods are described here.
http://tkyte.blogspot.com/2006/06/varying-in-lists.html
You would not use dynamic SQL. -
Populate a REF CURSOR from regular cursor...
Hi all,
I apologize if the answer to this is somewhere...I've been looking on the web for sometime and can't find an answer to the following problem. I have a Significant Events database that contains network based issues and problems. As problems are detected on the network an SE is issued and published. As the SE records are updated, NEW records are entered into the table and "linked" back to the original. Each update results in a new row. Thus, an SE with two updates would have a total of 3 lines. When the SE gets closed (set the column CLOSED to SYSDATE), only the "original" SE is closed, any updates are left open...aka, the CLOSED column is left null.
That said, I need a way to get the original and/or latest updated SE rows from the table. Thus, I am trying to use a PL/SQL package. The PL/SQL "must" return a REF CURSOR as the results are being passed to a client process.
My initial approach was within a PL/SQL procedure, I have an SQL statement that returns the SE originals. Once in that cursor I need to do the following:
- Attempt to fetch any linked SE rows.
- if no rows then
- add the original to the REF CURSOR.
- else
- find latest SE update
- add latest SE update to REF CURSOR.
- end if
My Question is : How do I manually "add" a row to a REF CURSOR?
If this is not possible, is there a way to populate a REF CURSOR from maybe another construct like:
TYPE ian_se_record is RECORD (
se_id number
,linked_se_id number
,submitted date
,updated date
,closed date
,segroup varchar2(150)
,incident_start_time varchar2(150)
,business_units_affected varchar2(150)
,officenum varchar2(1500)
,sedetails varchar2(4000)
TYPE ian_se_table is table of ian_se_record index by binary_integer;
With the above construct I could:
- Fill ian_se_table with the process described above.
- And finally select off ian_se_table into the REF CURSOR?
Any help would be greatly appreciated,
adymHi michaels,
I've put your solution in place, but can't seem to get it to run. The two types were moved out of the package and into real types as you said. Here's the function, for brevity, I've remove some of the less important code:
function ian_se_fetch return sys_refcursor
is
p_csr_events sys_refcursor;
cursor csr_items is
select
se_id
...removed for brevity...
/* END : csr_items */
ian_se_row ian_se_record;
ian_se_tbl ian_se_table;
l_lng_index number;
l_lng_linked number;
l_lng_id number;
begin
* OPEN : Open the main cursor of originals...
for the_item in csr_items loop
* CHECK : Check for any updates to the original...
l_lng_linked := 0;
select count(*)
into l_lng_linked
from sig_se_t src
where src.linked_se_id = the_item.se_id;
l_lng_id := 0; /* reset the se-id */
/* SE original...no linked records yet. */
if ( l_lng_linked = 0 ) then
l_lng_id := the_item.se_id;
/* SE updates...one or more updates are present. */
else
begin
select
se_id
into l_lng_id
from sig_se_t src
where src.linked_se_id = the_item.se_id
and rownum = 1
order by updated desc; /* latest update */
exception
when too_many_rows then
l_lng_id := the_item.se_id;
when others then
l_lng_id := 0;
end;
end if;
if ( l_lng_id != 0 ) then
select
se_id
,linked_se_id
,submitted
,updated
,closed
,segroup
,incident_start_time
,business_units_affected
,officenum || decode( nvl(impact,'1')
,'1',''
,decode(impact
,'NA', ''
,':' || impact
) impact
,sedetails
into ian_se_row.se_id
,ian_se_row.linked_se_id
,ian_se_row.submitted
,ian_se_row.updated
,ian_se_row.closed
,ian_se_row.segroup
,ian_se_row.incident_start_time
,ian_se_row.business_units_affected
,ian_se_row.officenum
,ian_se_row.sedetails
from sig_se_t src
where src.se_id = l_lng_id;
l_lng_index := nvl(ian_se_tbl.last,0)+1;
ian_se_tbl(l_lng_index).se_id := ian_se_row.se_id;
ian_se_tbl(l_lng_index).linked_se_id := ian_se_row.linked_se_id;
ian_se_tbl(l_lng_index).submitted := ian_se_row.submitted;
ian_se_tbl(l_lng_index).updated := ian_se_row.updated;
ian_se_tbl(l_lng_index).closed := ian_se_row.closed;
ian_se_tbl(l_lng_index).segroup := ian_se_row.segroup;
ian_se_tbl(l_lng_index).incident_start_time := ian_se_row.incident_start_time;
ian_se_tbl(l_lng_index).business_units_affected := ian_se_row.business_units_affected;
ian_se_tbl(l_lng_index).officenum := ian_se_row.officenum;
ian_se_tbl(l_lng_index).sedetails := ian_se_row.sedetails;
end if;
end loop;
* REF CURSOR : Open the ref cursor on the dataset...
if ( nvl(ian_se_tbl.last,0) = 0 ) then
p_csr_events := null;
else
open p_csr_events for
select *
from table (cast ( ian_se_tbl as ian_se_table ));
end if;
return p_csr_events;
end;Here's the test. I keep getting the same error ORA-06530:
SQL> variable v refcursor;
SQL> exec :v:=pkg_ian.ian_se_fetch;
BEGIN :v:=pkg_ian.ian_se_fetch; END;
ERROR at line 1:
ORA-06530: Reference to uninitialized composite
ORA-06512: at "N0002501.PKG_IAN", line 131
ORA-06512: at line 1
SQL> print v
ERROR:
ORA-24338: statement handle not executedOther things I tried:
- The ian_se_fetch() function was a procedure using an in out parameter...same error.
- Wrote a small anonymous block and tried to LOOP/FETCH. Same ORA-06530 error.
P.S. Line 131 of pkg_ian is the SELECT ... INTO ian_se_row.se_id, ...
Any help would be greatly appreciated,
tia,
adym
Message was edited by:
alink -
Different error messages from different env while fetching ref cursor
Hi<br>
I have a package where i need to call one of the procedure.I this <br>
procedure i am returning a refcursor as out parameter.Before returning refcursor i <br>
am doing i am checking a condition if it is satisfied then I am saying return or else<br>
it will proceed and refcursor is assigned for out parameter.So i am speakig about <br>
the condition where i am exiting from procedure before refcursor parameter is <br>
assigned .And later i am tring to fetch from that cursor .So i am getting different <br>
kinds of errors which i described as follows <br>
<br>
<br>
So If execute that procedure from sqlplus uing <br>
<br>
<br>
var m ref cursor<br>
DECLARE<br>
Y NUMBER;<br>
Z NUMBER;<br>
A NUMBER;<br>
BEGIN<br>
A:=campa.dtl_inq(2,100070875,'R',Y,Z,:M);<br>
END;<br>
<br>
Then if say<br>
Print m<br>
It gives <br>
<br>
ORA-24338: statement handle not executed<br>
<br>
And if i execute this using vb application <br>
<br>
I am getting following error <br>
<br>
ORA-01023: Cursor context not found (Invalid cursor number)<br>
<br>
So i am serching the reason for different errors<br>
<br>
Regards<br>
vamsi krishna<br>The error depends on exactly what OCI calls the client software makes in accessing this invalid (null) ref cursor variable.
It would seem that SQL*Plus makes different calls than what your code and Visual Basic does - thus the different error messages returned by the two applications. -
<p>I am trying to call an Oracle stored procedure within SQR thatreturns a ref cursor. I am able to successfully do this onlyif I run the program as the schema owner. I read that SQRneeds to be able to do a describe on the stored procedure in orderfor the program to work. I can do a describe but only if Iinclude the schema owner (ex. schema_owner.stored_procedure). So, logically, I tried to add the schema owner to the storedprocedure name within sqr. When I do this I get the error(SQR 3918) Missing Stored Procedure or Function.</p><p> </p><p>Here is the syntax below:</p><p>execute on-error=ora_err do=print_plan_type<br> @#retVal=HRIS.HRIS_HRS_DS_PACKAGE.Get_Plan_Type_List@rc01=$planCursor OUT<br> INTO &pc_ext_app_id varchar2(3)</p><p> </p><p>Any thoughts on how I can get SQR to recognize the schemaowner?<br></p>
Here's a link:
PL/SQL Users Guide and Reference
cheers,
Anthony -
Is it possible to ref cursor(result set) as in parameter to procedure/funct
Hi,
I am getting a resultset/ref cursor from the Java side to the procedure/function as in parameter. Is this possible in oracle 10g.
If yes can body send the links/suggestions describing some examples.
Thanks,I am getting a resultset/ref cursor from the Java
side to the procedure/function as in parameter. Is
this possible in oracle 10g. It is possible, but it sounds like you have your application design entirely backwards.
A ref cursor is designed to be used to pass a result set from a stored procedure to a client or calling application.
So while you could use a screwdriver to hammer in a nail, you probably would not want to. -
Odd error while opening a ref cursor
Hi.
I have a procedure in a package that has both in and out parameters. One of those out parameters is a ref cursor. The procedure creates a dynamic query and then executes it, then it opens the cursor:
PROCEDURE PROC(
A IN VARCHAR2,
B IN VARCHAR2,
C OUT TYPES.cursorType; --(TYPES is a package whose only use is to declare a cursor type)
) IS
--DECLARATIONS
OPEN C FOR 'SELECT A, B, C, D...';
END;
When I execute the package in an anonymous block it throws the error:
ORA-00938: not enough arguments for function, just in the line where the cursor is being opened.
Any ideas?is everything defined correctly?
create or replace package types as
type cursorType is ref cursor;
end types;
SQL> set serveroutput on
SQL> declare
2
3 ref_C types.cursorType;
4
5 v_a varchar2(1);
6 v_b varchar2(1);
7 v_c varchar2(1);
8 v_d varchar2(1);
9
10 procedure Proc (a in varchar2
11 ,b in varchar2
12 ,C out types.cursorType) as
13
14 begin
15 open C for 'select :1, :2, ''c'', ''d'' from dual' using a, b;
16 end Proc;
17 begin
18
19
20 Proc('a', 'b', ref_C);
21
22 fetch ref_C into v_a, v_b, v_c, v_d;
23 if (ref_C%found) then
24 dbms_output.put_line(v_a);
25 dbms_output.put_line(v_b);
26 dbms_output.put_line(v_c);
27 dbms_output.put_line(v_d);
28 end if;
29
30
31 end;
32 /
a
b
c
dP;
Edited by: bluefrog on Feb 18, 2010 6:07 PM -
The query below will return values in the form of
bu seq eligible
22 2345 Y
22 2345 N
22 1288 N
22 1458 Y
22 1458 N
22 1234 Y
22 1333 N
What I am trying to accomplish is to loop through the records returned.
for each seq if there is a 'N' in the eligible column return no record for that seq
eg seq 2345 has 'Y' and 'N' thus no record should be returned.
seq 1234 has only a 'Y' then return the record
seq 1333 has 'N' so return no record.
How would I accomplish this with a ref Cursor and pass the values to the front end application.
Procedure InvalidNOs(io_CURSOR OUT T_CURSOR)
IS
v_CURSOR T_CURSOR;
BEGIN
OPEN v_CURSOR FOR
' select bu, seq, eligible ' ||
' from (select bu, seq, po, tunit, tdollar,eligible,max(eligible) over () re ' ||
' from (select bu, seq, po, tunit, tdollar,eligible ' ||
' from ( ' ||
' select bu, seq, po, tunit, tdollar, eligible, sum(qty) qty, sum(price*qty) dollars ' ||
' from ' ||
' ( select /*+ use_nl(t,h,d,s) */ ' ||
' h.business_unit_id bu, h.edi_sequence_id seq, d.edi_det_sequ_id dseq, ' ||
' s.edi_size_sequ_id sseq, h.po_number po, h.total_unit tUnit, h.total_amount tDollar, ' ||
' s.quantity qty, s.unit_price price,' ||
' (select (case when count(*) = 0 then ''Y'' else ''N'' end) ' ||
' from sewn.NT_edii_po_det_error ' ||
' where edi_det_sequ_id = d.edi_det_sequ_id ' ||
' ) eligible ' ||
' from sewn.nt_edii_purchase_size s, sewn.nt_edii_purchase_det d, ' ||
' sewn.nt_edii_purchase_hdr h, sewn.nt_edii_param_temp t ' ||
' where h.business_unit_id = t.business_unit_id ' ||
' and h.edi_sequence_id = t.edi_sequence_id ' ||
' and h.business_unit_id = d.business_unit_id ' ||
' and h.edi_sequence_id = d.edi_sequence_id ' ||
' and d.business_unit_id = s.business_unit_id ' ||
' and d.edi_sequence_id = s.edi_sequence_id ' ||
' and d.edi_det_sequ_id = s.edi_det_sequ_id ' ||
' ) group by bu, seq, po, tunit, tdollar, eligible ' ||
' ) ' ||
' group by bu, seq, po, tunit, tdollar, eligible)) ';
io_CURSOR := v_CURSOR;
END InvalidNOs;One remark why you should not use the assignment between ref cursor
variables.
(I remembered I saw already such thing in your code).
Technically you can do it but it does not make sense and it can confuse your results.
In the opposite to usual variables, when your assignment copies value
from one variable to another, cursor variables are pointers to the memory.
Because of this when you assign one cursor variable to another you just
duplicate memory pointers. You don't copy result sets. What you do for
one pointer is that you do for another and vice versa. They are the same.
I think the below example is self-explained:
SQL> /* usual variables */
SQL> declare
2 a number;
3 b number;
4 begin
5 a := 1;
6 b := a;
7 a := a + 1;
8 dbms_output.put_line('a = ' || a);
9 dbms_output.put_line('b = ' || b);
10 end;
11 /
a = 2
b = 1
PL/SQL procedure successfully completed.
SQL> /* cursor variables */
SQL> declare
2 a sys_refcursor;
3 b sys_refcursor;
4 begin
5 open a for select empno from emp;
6 b := a;
7 close b;
8
9 /* next action is impossible - cursor already closed */
10 /* a and b are the same ! */
11 close a;
12 end;
13 /
declare
ERROR at line 1:
ORA-01001: invalid cursor
ORA-06512: at line 11
SQL> declare
2 a sys_refcursor;
3 b sys_refcursor;
4 vempno emp.empno%type;
5
6 begin
7 open a for select empno from emp;
8 b := a;
9
10 /* Fetch first row from a */
11 fetch a into vempno;
12 dbms_output.put_line(vempno);
13
14 /* Fetch from b gives us SECOND row, not first -
15 a and b are the SAME */
16
17 fetch b into vempno;
18 dbms_output.put_line(vempno);
19
20
21 end;
22 /
7369
7499
PL/SQL procedure successfully completed.Rgds.
Message was edited by:
dnikiforov -
Dynamic sql and ref cursors URGENT!!
Hi,
I'm using a long to build a dynamic sql statement. This is limited by about 32k. This is too short for my statement.
The query results in a ref cursor.
Does anyone have an idea to create larger statement or to couple ref cursors, so I can execute the statement a couple of times and as an result I still have one ref cursor.
Example:
/* Determine if project is main project, then select all subprojects */
for i in isMainProject loop
if i.belongstoprojectno is null then
for i in ProjectSubNumbers loop
if ProjectSubNumbers%rowcount=1 then
SqlStatement := InitialStatement || i.projectno;
else
SqlStatement := SqlStatement || PartialStatement || i.projectno;
end if;
end loop;
else
for i in ProjectNumber loop
if ProjectNumber%rowcount=1 then
SqlStatement := InitialStatement || i.projectno;
else
SqlStatement := SqlStatement || PartialStatement || i.projectno;
end if;
end loop;
end if;
end loop;
/* Open ref cursor */
open sql_output for SqlStatement;
Thanks in advance,
Jeroen Muis
KCI Datasystems BV
mailto:[email protected]Example for 'dynamic' ref cursor - dynamic WHERE
(note that Reports need 'static' ref cursor type
for building Report Layout):
1. Stored package
CREATE OR REPLACE PACKAGE report_dynamic IS
TYPE type_ref_cur_sta IS REF CURSOR RETURN dept%ROWTYPE; -- for Report Layout only
TYPE type_ref_cur_dyn IS REF CURSOR;
FUNCTION func_dyn (p_where VARCHAR2) RETURN type_ref_cur_dyn;
END;
CREATE OR REPLACE PACKAGE BODY report_dynamic IS
FUNCTION func_dyn (p_where VARCHAR2) RETURN type_ref_cur_dyn IS
ref_cur_dyn type_ref_cur_dyn;
BEGIN
OPEN ref_cur_dyn FOR
'SELECT * FROM dept WHERE ' | | NVL (p_where, '1 = 1');
RETURN ref_cur_dyn;
END;
END;
2. Query PL/SQL in Reports
function QR_1RefCurQuery return report_dynamic.type_ref_cur_sta is
begin
return report_dynamic.func_dyn (:p_where);
end;
Regards
Zlatko Sirotic
null -
ORA-01008 with ref cursor and dynamic sql
When I run the follwing procedure:
variable x refcursor
set autoprint on
begin
Crosstab.pivot(p_max_cols => 4,
p_query => 'select job, count(*) cnt, deptno, row_number() over (partition by job order by deptno) rn from scott.emp group by job, deptno',
p_anchor => Crosstab.array('JOB'),
p_pivot => Crosstab.array('DEPTNO', 'CNT'),
p_cursor => :x );
end;I get the following error:
^----------------
Statement Ignored
set autoprint on
begin
adsmgr.Crosstab.pivot(p_max_cols => 4,
p_query => 'select job, count(*) cnt, deptno, row_number() over (partition by
p_anchor => adsmgr.Crosstab.array('JOB'),
p_pivot => adsmgr.Crosstab.array('DEPTNO', 'CNT'),
p_cursor => :x );
end;
ORA-01008: not all variables bound
I am running this on a stored procedure as follows:
create or replace package Crosstab
as
type refcursor is ref cursor;
type array is table of varchar2(30);
procedure pivot( p_max_cols in number default null,
p_max_cols_query in varchar2 default null,
p_query in varchar2,
p_anchor in array,
p_pivot in array,
p_cursor in out refcursor );
end;
create or replace package body Crosstab
as
procedure pivot( p_max_cols in number default null,
p_max_cols_query in varchar2 default null,
p_query in varchar2,
p_anchor in array,
p_pivot in array,
p_cursor in out refcursor )
as
l_max_cols number;
l_query long;
l_cnames array;
begin
-- figure out the number of columns we must support
-- we either KNOW this or we have a query that can tell us
if ( p_max_cols is not null )
then
l_max_cols := p_max_cols;
elsif ( p_max_cols_query is not null )
then
execute immediate p_max_cols_query into l_max_cols;
else
RAISE_APPLICATION_ERROR(-20001, 'Cannot figure out max cols');
end if;
-- Now, construct the query that can answer the question for us...
-- start with the C1, C2, ... CX columns:
l_query := 'select ';
for i in 1 .. p_anchor.count
loop
l_query := l_query || p_anchor(i) || ',';
end loop;
-- Now add in the C{x+1}... CN columns to be pivoted:
-- the format is "max(decode(rn,1,C{X+1},null)) cx+1_1"
for i in 1 .. l_max_cols
loop
for j in 1 .. p_pivot.count
loop
l_query := l_query ||
'max(decode(rn,'||i||','||
p_pivot(j)||',null)) ' ||
p_pivot(j) || '_' || i || ',';
end loop;
end loop;
-- Now just add in the original query
l_query := rtrim(l_query,',')||' from ( '||p_query||') group by ';
-- and then the group by columns...
for i in 1 .. p_anchor.count
loop
l_query := l_query || p_anchor(i) || ',';
end loop;
l_query := rtrim(l_query,',');
-- and return it
execute immediate 'alter session set cursor_sharing=force';
open p_cursor for l_query;
execute immediate 'alter session set cursor_sharing=exact';
end;
end;
/I can see from the error message that it is ignoring the x declaration, I assume it is because it does not recognise the type refcursor from the procedure.
How do I get it to recognise this?
Thank you in advanceThank you for your help
This is the version of Oracle I am running, so this may have something to do with that.
Oracle9i Enterprise Edition Release 9.2.0.8.0 - Production
With the Partitioning, OLAP and Oracle Data Mining options
JServer Release 9.2.0.8.0 - Production
I found this on Ask Tom (http://asktom.oracle.com/pls/asktom/f?p=100:11:0::::P11_QUESTION_ID:3027089372477)
Hello, Tom.
I have one bind variable in a dynamic SQL expression.
When I open cursor for this sql, it gets me to ora-01008.
Please consider:
Connected to:
Oracle8i Enterprise Edition Release 8.1.7.4.1 - Production
JServer Release 8.1.7.4.1 - Production
SQL> declare
2 type cur is ref cursor;
3 res cur;
4 begin
5 open res for
6 'select * from (select * from dual where :p = 1) connect by 1 = 1'
7 using 1;
8 end;
9 /
declare
ERROR at line 1:
ORA-01008: not all variables bound
ORA-06512: at line 5
SQL> declare
2 type cur is ref cursor;
3 res cur;
4 begin
5 open res for
6 'select * from (select * from dual where :p = 1) connect by 1 = 1'
7 using 1, 2;
8 end;
9 /
PL/SQL procedure successfully completed.
And if I run the same thing on 10g -- all goes conversely. The first part runs ok, and the second
part reports "ORA-01006: bind variable does not exist" (as it should be, I think). Remember, there
is ONE bind variable in sql, not two. Is it a bug in 8i?
What should we do to avoid this error running the same plsql program code on different Oracle
versions?
P.S. Thank you for your invaluable work on this site.
Followup June 9, 2005 - 6pm US/Eastern:
what is the purpose of this query really?
but it would appear to be a bug in 8i (since it should need but one). You will have to work that
via support. I changed the type to tarray to see if the reserved word was causing a problem.
variable v_refcursor refcursor;
set autoprint on;
begin
crosstab.pivot (p_max_cols => 4,
p_query =>
'SELECT job, COUNT (*) cnt, deptno, ' ||
' ROW_NUMBER () OVER ( ' ||
' PARTITION BY job ' ||
' ORDER BY deptno) rn ' ||
'FROM emp ' ||
'GROUP BY job, deptno',
p_anchor => crosstab.tarray ('JOB'),
p_pivot => crosstab.tarray ('DEPTNO', 'CNT'),
p_cursor => :v_refcursor);
end;
/Was going to use this package as a stored procedure in forms but I not sure it's going to work now.
Maybe you are looking for
-
F-51: Balancing field "Profit Center" in line item 001 not filled
Hi, When trying to clear the Vendors using F-51, I'm getting a messages saying:'Balancing field "Profit Center" in line item 001 not filled'. When I simulate I'm able to see the profit centers getting picked up against all the other line items, excep
-
Dear Friends, I have upload one program for customer ageing report. In that there is statements like GET LFA1, GET BSIK etc. when i save and check it throughs an error that "lfa1 is not defined for the current logical database'. but these statements
-
Exporting to quicktime for web
Can you tell me the best quality setting when exporting a clip from final cut for use on a website. The clip has been green screened with the filter and it looks clear in the viewer, but when watching it in quicktime and on the web, its fuzzy? Any id
-
Expressions editing bug (os x)
Hi there when editing an expression, whenever using copy/paste, or dragging a selection to reposition it in the expression, after exiting the editing some of the text disappears. if valid, the expression actually works, but i can see only a portion o
-
Hello all, I am trying to see one enhancement that I created in the system but I can´t see the code. I go to SW84 transaction, put the name and appears, but when I click on button to see the code, I can´t see nothing... What can I do? Thanks in advan