Passing Ref Cursor as parameter to object type method
I am encountering a problem passing a parameter of type REF CURSOR to methods of a set of object types I am developing.
Here is an example of what I am trying to do:
create or replace package p1 as
type c_Cursor is ref cursor;
end p1;
create or replace type t_Object as object
not instantiable method m1(p_Cursor in p1.c_Cursor) return varchar2
) not instantiable not final;
create or replace type t_Subtype under t_Object as
overriding method m1(p_Cursor in p1.c_Cursor)
return varchar2
The problem is that the PL/SQL compiler gives the error message PLS-00201 "p1.c_Cursor" not defined.
According to my PL/SQL book (SF's Oracle PL/SQL Programming) the only way to use a ref cursor as a parameter to functions/procedures is to wrap them in a package. Indeed I have developed a test procedure in a different package that uses p1.c_Cursor as a parameter and it works fine.
Oracle's documemtation suggests that object security (roles etc) can cause this error but as all the objects are being created in the same schema I don't see how this should be a problem.
If anyone can suggest how to get around this problem I will be very grateful.
BTW, if there are any mistakes in my sample code it's because I am writing it from memory as I don't have Internet access at work.
Thanks,
Charles.
Thanks for your reply. I am still baffled as to why it doesn't work but, as you correctly point out, SYS_REFCURSOR works just fine. I figured that out earlier today and now the problem is solved.
Charles.
Similar Messages
-
Passing Ref Cursor to Oracle Stored Procedure Via C#
Hi all,
I am new to oracle and stuck with an issue. I have three insert stored procedures for three different tables. Two of them have multiple rows to be inserted, which is currently done via iterating through each row and insert to db in C# code. My requirement is to merge these three procedures in one and instead of iterating from C# code send table rows as (ref cursor or collection) to procedure and the procedure will handle the rest.
I read that ref cursor only works if you're data is in database as it reference the memory but in my case data is build on client side.
I am using Oracle 11i and ASP.Net 2.0
Can any help me on this please?
Edited by: 929463 on Apr 23, 2012 12:38 AM929463 wrote:
I am new to oracle and stuck with an issue. I have three insert stored procedures for three different tables. Two of them have multiple rows to be inserted, which is currently done via iterating through each row and insert to db in C# code. My requirement is to merge these three procedures in one and instead of iterating from C# code send table rows as (ref cursor or collection) to procedure and the procedure will handle the rest.Why a single procedure? How is the procedure to determine the target table to insert the data into? And please - no dynamic SQL as that is 99% of the time wrong.
A ref cursor is something that PL/SQL creates - with the purpose of passing the cursor handle to your code. This enables the actual SQL statement for that cursor to be moved from client code, into a PL/SQL stored proc. It abstracts the client from having to understand SQL, understand the data model and so on. All clients use the same PL/SQL proc and thus the same code for creating that cursor. Thus no issue of some clients getting it half right or half wrong and dealing with data inconsistencies between clients.
The PL/SQL proc can be tuned and optimised, modified for catering for data model changes and so on. Without your client code having to be even recompiled as it is isolated against these server changes.
For all other interaction (running PL/SQL code, doing insert/update/delete/etc SQL statements), you need to create the cursor yourself in your code.
Also, the SQL engine only sees cursors. There are no differences between cursors. The client (e.g. PL/SQL) can call it a reference cursor, or an implicit cursor, or a DBMS_SQL cursor.. the SQL engine does not know that and does not care.
A ref cursor is simply a special type of client interface to a SQL cursor, allowing PL/SQL to create that SQL cursor and then pass the handle of that SQL cursor to other code to consume that cursor.
Okay, so if you want to insert data, you need in your code to create a cursor. This can be a SQL INSERT cursor - the actual insert statement. Or it can be a PL/SQL call - an anonymous PL/SQL code block that calls a stored proc that performs the insert (after applying validation and business logic).
The cursor will have one or more bind variables. Your client will pass values for these variables and the server-side code (SQL or PL/SQL) will be executed using this as variable data.
You can for example create a cursor as follows:
begin
DoFunkyInsert( :1, :2, :3 );
end;
{code}
3 bind variables are expected. You can now in the client build an array for each of these variables, containing a 100 values each (total of a 100 rows to insert). Do a single execute of the cursor, and tell Oracle that the bind is actually a 100 element array.
The complete array ships to Oracle - Oracle opens a loop and execute the cursor for each element in the array.
This is called bulk binding.
An alternative approach is to define the bind variable as a collection (a non-scalar value). And then code the PL/SQL procedure to open a loop and iterate through the collection/array, inserting a row per iteration.
The binding itself is more complex as your code know needs to understand Oracle object types and be able to define an array/collection that is a valid Oracle non-scalar data type.
The +Oracle Call Interface+ (OCI) is quite flexible in this regard. However, as you work via an abstraction layer (e.g. ADO, OleDB, ODBC, etc) your code is subject to whatever functionality this abstraction layer makes available to your code. And this is seldom includes all the power, functionality and flexibility of the (more complex) OCI itself. -
How to call a Stored Procedure with a REF CURSOR output parameter
I am looking forward an example that call a stored function/procedure with a REF CURSOR output parameter and get the result.
In other words, I have a stored function/procedure that execute a SELECT statement using the OCI library and then it could get the values of each column and each row.
I put a code snippet, it have only the main thing to call a simple stored procedure and print the name of each column of the cursor, but I couldn´t to print out the values in the table that call the stored procedure.
I understand that the next step, it is to call a OCIStmtFetch.
How to associate the cursor with the OCIStmtFetch?
If you need more information, only tell me.
I am using ANSI C with HP-UX Operative System (C for HP-UX) and Oracle 10g.
Regards.
Antonio Garcia
/* callOracleSP */
#include <stdio.h>
#include <string.h>
#include <oci.h>
#include <stdlib.h>
char* pConnectChar ="server";
char* pUsernameChar = "user";
char* pPasswordChar = "passwd";
char* sqlCharArray1 = "BEGIN SP_GETCITIES(:s, :c); END;";
int retval;
ub4 parmcnt=0;
ub4 pos2=0;
text *pcoln[20];
ub4 namelen[20];
char state_key[5];
OCIStmt* pOciStatement;
OCIStmt* pOciStatCursor;
OCIError* pOciError;
OCIEnv* pOciEnviron;
OCIServer* pOciServer;
OCISession* pOciSession;
OCISvcCtx* pOciServiceContext;
OCIBind* pOciBind[500];
OCIParam* pOciParam;
int main()
retval = OCIEnvCreate(&pOciEnviron, OCI_DEFAULT, NULL, NULL, NULL, NULL,0,NULL);
retval = OCIEnvInit(&pOciEnviron, OCI_DEFAULT, 0, NULL);
retval = OCIHandleAlloc(pOciEnviron, (void **)&pOciError, OCI_HTYPE_ERROR, 0, NULL);
retval = OCIHandleAlloc(pOciEnviron, (void **)&pOciServiceContext, OCI_HTYPE_SVCCTX, 0, NULL);
retval = OCIHandleAlloc(pOciEnviron, (void **)&pOciStatement, OCI_HTYPE_STMT, 0, NULL);
retval = OCILogon(pOciEnviron,pOciError,&pOciServiceContext,(unsigned char *)pUsernameChar,
strlen(pUsernameChar), (unsigned char *)pPasswordChar, strlen(pPasswordChar),
(unsigned char *)pConnectChar,strlen(pConnectChar));
printf("OCILogon retval=%d\n",retval);
retval = OCIStmtPrepare(pOciStatement, pOciError, (unsigned char *)sqlCharArray1,strlen(sqlCharArray1),
OCI_NTV_SYNTAX, OCI_DEFAULT);
printf("StmtPrepare retval=%d\n",retval);
retval = OCIHandleAlloc(pOciEnviron, (void **)&pOciStatCursor, OCI_HTYPE_STMT, 0, NULL);
retval = OCIBindByPos(pOciStatement,&pOciBind[0], pOciError, (ub4) 1, (void *)&state_key,
(sb4) sizeof(state_key), SQLT_STR, (void *) 0, (ub2 *) 0, (ub2 *)0,(ub4)0, (ub4 *)0, (ub4) OCI_DEFAULT);
printf("BindByPos OCI_HTYPE_STMT retval=%d\n",retval);
retval = OCIBindByPos(pOciStatement,&pOciBind[1], pOciError, (ub4) 2, (void *)&pOciStatCursor,
(sb4) 0, SQLT_RSET, (void *) 0, (ub2 *) 0, (ub2 *)0,(ub4)0, (ub4 *)0, (ub4) OCI_DEFAULT);
printf("BindByPos OCI_HTYPE_STMT retval=%d\n",retval);
strcpy(state_key,"CA");
retval = OCIStmtExecute(pOciServiceContext, pOciStatement, pOciError, (ub4)1, (ub4) 0,
(OCISnapshot *)NULL, (OCISnapshot *)NULL, (ub4) OCI_DEFAULT);
printf("StmtExecute retval=%d\n",retval);
/* How to get the values of the cursor? */
/* Get number of parameters of the Cursor */
OCIAttrGet((void *) pOciStatCursor, (ub4)OCI_HTYPE_STMT, (void*) &parmcnt,(ub4 *) 0,
(ub4)OCI_ATTR_PARAM_COUNT, pOciError);
printf("\nNumber of parameters of the cursor = %d\n",parmcnt);
for (int pos = 1; pos <= (int)parmcnt; pos++)
OCIAttrGet((void *) pOciStatCursor, (ub4)OCI_HTYPE_STMT, (void*) &pos2,(ub4 *) 0,
(ub4)OCI_ATTR_CURRENT_POSITION, pOciError);
retval = OCIParamGet((void *)pOciStatCursor, (ub4)OCI_HTYPE_STMT, pOciError, (void **)&pOciParam,
(ub4) pos );
OCIAttrGet((void*) pOciParam, (ub4) OCI_DTYPE_PARAM,(void*) &pcoln[pos-1],(ub4 *) &namelen[pos-1],
(ub4) OCI_ATTR_NAME,(OCIError *)pOciError );
for (int i = 1; i <=(int)parmcnt; i++)
printf("Column %i\tNAME = %.*s\n",i,namelen[i-1],pcoln[i-1]);
return 0;
This is the script that create the table, insert records and create the stored procedure
CREATE TABLE CITIES (
STATE_CODE VARCHAR2(2) NULL,
CITY_CODE NUMBER(15,5) NULL,
CITY_NAME VARCHAR2(30) NULL
INSERT INTO CITIES(STATE_CODE, CITY_CODE, CITY_NAME)
VALUES('CA', 30, 'SAN DIEGO')
INSERT INTO CITIES(STATE_CODE, CITY_CODE, CITY_NAME)
VALUES('CA', 40, 'SACRAMENTO')
INSERT INTO CITIES(STATE_CODE, CITY_CODE, CITY_NAME)
VALUES('FL', 10, 'MIAMI')
INSERT INTO CITIES(STATE_CODE, CITY_CODE, CITY_NAME)
VALUES('FL', 20, 'ORLANDO')
INSERT INTO CITIES(STATE_CODE, CITY_CODE, CITY_NAME)
VALUES('NY', 10, 'NEW YORK')
INSERT INTO CITIES(STATE_CODE, CITY_CODE, CITY_NAME)
VALUES('NY', 20, 'ALBANY')
INSERT INTO CITIES(STATE_CODE, CITY_CODE, CITY_NAME)
VALUES('CA', 10, 'LOS ANGELES')
INSERT INTO CITIES(STATE_CODE, CITY_CODE, CITY_NAME)
VALUES('CA', 20, 'SAN FRANCISCO')
CREATE OR REPLACE PACKAGE globalPkg AUTHID CURRENT_USER AS
/* The following are T/SQL specific global variables. */
TYPE RCT1 IS REF CURSOR;/*new weak cursor definition*/
END globalPkg;
CREATE OR REPLACE PROCEDURE SP_ADDCITY(
P_STATE_CODE IN VARCHAR,
P_CITY_CODE IN NUMBER,
P_CITY_NAME IN VARCHAR2,
P_RETURN IN OUT NUMBER)
AS
StoO_error INTEGER;
StoO_selcnt INTEGER;
StoO_rowcnt INTEGER;
StoO_errmsg VARCHAR2(255);
BEGIN
StoO_rowcnt := 0;
StoO_error := 0;
StoO_selcnt := 0;
P_RETURN := 0;
INSERT INTO CITIES (STATE_CODE, CITY_CODE, CITY_NAME)
VALUES (P_STATE_CODE, P_CITY_CODE, P_CITY_NAME);
StoO_rowcnt := SQL%ROWCOUNT;
EXCEPTION
WHEN TOO_MANY_ROWS THEN
StoO_rowcnt := 2;
WHEN OTHERS THEN
StoO_rowcnt := 0;
StoO_selcnt := 0;
StoO_error := SQLCODE;
StoO_errmsg := SQLERRM;
IF StoO_error != 0 THEN
BEGIN
P_RETURN := 1;
RETURN;
END;
END IF;
END;
CREATE OR REPLACE PROCEDURE SP_GETCITIES(
STATE_KEY IN VARCHAR,
RC1 IN OUT globalPkg.RCT1)
AS
StoO_error INTEGER;
StoO_selcnt INTEGER;
StoO_rowcnt INTEGER;
StoO_errmsg VARCHAR2(255);
BEGIN
StoO_rowcnt := 0;
StoO_error := 0;
StoO_selcnt := 0;
OPEN RC1 FOR
SELECT STATE_CODE, CITY_CODE, CITY_NAME
FROM CITIES
WHERE STATE_CODE = STATE_KEY
ORDER BY CITY_CODE;
StoO_rowcnt := SQL%ROWCOUNT;
EXCEPTION
WHEN OTHERS THEN
StoO_rowcnt := 0;
StoO_error := SQLCODE;
StoO_errmsg := SQLERRM;
END;
/Hi Mark,
Thanks for your recommendations.
I change the code with OCIDefineByPos, one for each parameter from cursor and then use the OCIStmtFetch.
I don´t receive a error when call OCIDefineByPos, but when I call OCIStmtFetch receive a -1 error number.
What is wrong with the code?
The script is the same.
I need your help!
Best Regards!
Antonio Garcia (Mexico)
This the new code:
#include <stdio.h>
#include <string.h>
#include <oci.h>
#include <stdlib.h>
char* pConnectChar ="ORAC617";
char* pUsernameChar = "C617_005_DBO_01";
char* pPasswordChar = "Tempora1";
char* sqlCharArray1 = "BEGIN SP_GETCITIES(:s, :c); END;";
int retval;
ub4 parmcnt=0;
ub4 pos2=0;
sb2 *c_indp;
text *pcoln[20], *name,*name2;
ub4 namelen[20],len;
ub2 type,size;
char state_key[5];
OCIDefine *pdef;
OCIBind *p_bnd;
ub1 **c_buf;
OCIStmt* pOciStatement; /* Statement handle */
OCIStmt* pOciStatCursor; /* Statement handle */
OCIError* pOciError; /* Error handle */
OCIEnv* pOciEnviron; /* Environment handle */
OCIServer* pOciServer; /* Server handle */
OCISession* pOciSession; /* Session handle */
OCISvcCtx* pOciServiceContext; /* Service Context handle */
OCIBind* pOciBind[500]; /* Bind handle */
OCIParam* pOciParam; /* Param handle */
int OCI_Fetch(OCIStmt *p_select,OCIError *p_err, int *piOcc)
int iOcc, rc;
rc=OCIStmtFetch(p_select,p_err,1,OCI_FETCH_NEXT,OCI_DEFAULT);
printf("rc fetch %i",rc);
if(rc==0&&piOcc!=NULL){
printf("entro al if");
iOcc=*piOcc;
*piOcc=iOcc+1;
return rc;
int main()
int pos,i=0,rc;
retval = OCIEnvCreate(&pOciEnviron, OCI_DEFAULT, NULL, NULL, NULL, NULL,0,NULL);
printf("EnvCreate retval=%d\n", retval);
retval = OCIEnvInit(&pOciEnviron, OCI_DEFAULT, 0, NULL);
printf("EnvInit retval=%d\n",retval);
retval = OCIHandleAlloc(pOciEnviron, (void **)&pOciError, OCI_HTYPE_ERROR, 0, NULL);
printf("HandleAlloc OCI_HTYPE_ERROR retval=%d\n",retval);
retval = OCIHandleAlloc(pOciEnviron, (void **)&pOciServiceContext, OCI_HTYPE_SVCCTX, 0, NULL);
printf("HandleAlloc OCI_HTYPE_SVCCTX retval=%d\n",retval);
retval = OCIHandleAlloc(pOciEnviron, (void **)&pOciStatement, OCI_HTYPE_STMT, 0, NULL);
printf("HandleAlloc OCI_HTYPE_STMT retval=%d\n",retval);
retval = OCILogon(pOciEnviron,pOciError,&pOciServiceContext,(unsigned char *)pUsernameChar,
strlen(pUsernameChar), (unsigned char *)pPasswordChar, strlen(pPasswordChar),
(unsigned char *)pConnectChar,strlen(pConnectChar));
printf("OCILogon retval=%d\n",retval);
retval = OCIStmtPrepare(pOciStatement, pOciError, (unsigned char *)sqlCharArray1,strlen(sqlCharArray1),
OCI_NTV_SYNTAX, OCI_DEFAULT);
printf("StmtPrepare retval=%d\n",retval);
retval = OCIHandleAlloc(pOciEnviron, (void **)&pOciStatCursor, OCI_HTYPE_STMT, 0, NULL);
printf("HandleAlloc OCI_HTYPE_STMT retval=%d\n",retval);
retval = OCIBindByPos(pOciStatement,&pOciBind[0], pOciError, (ub4) 1, (void *)&state_key,
(sb4) sizeof(state_key), SQLT_STR, (void *) 0, (ub2 *) 0, (ub2 *)0,(ub4)0, (ub4 *)0, (ub4) OCI_DEFAULT);
printf("BindByPos OCI_HTYPE_STMT retval=%d\n",retval);
retval = OCIBindByPos(pOciStatement,&pOciBind[1], pOciError, (ub4) 2, (void *)&pOciStatCursor,
(sb4) 0, SQLT_RSET, (void *) 0, (ub2 *) 0, (ub2 *)0,(ub4)0, (ub4 *)0, (ub4) OCI_DEFAULT);
printf("BindByPos OCI_HTYPE_STMT retval=%d\n",retval);
strcpy(state_key,"CA");
retval = OCIStmtExecute(pOciServiceContext, pOciStatement, pOciError, (ub4)1, (ub4) 0,
(OCISnapshot *)NULL, (OCISnapshot *)NULL, (ub4) OCI_DEFAULT);
printf("StmtExecute retval=%d\n",retval);
c_buf=(ub1 **)calloc(sizeof(ub1 *),3);
c_indp=(sb2 *)calloc(sizeof(sb2 *),3);
// Get number of parameters of the Cursor
OCIAttrGet((void *) pOciStatCursor, (ub4)OCI_HTYPE_STMT, (void*) &parmcnt,(ub4 *) 0,
(ub4)OCI_ATTR_PARAM_COUNT, pOciError);
printf("\nNumber of parameters of the cursor = %d\n",parmcnt);
for (pos = 1; pos <= (int)parmcnt; pos++)
OCIAttrGet((void *) pOciStatCursor, (ub4)OCI_HTYPE_STMT, (void*) &pos2,(ub4 *) 0,
(ub4)OCI_ATTR_CURRENT_POSITION, pOciError);
retval = OCIParamGet((void *)pOciStatCursor, (ub4)OCI_HTYPE_STMT, pOciError, (void **)&pOciParam,(ub4) pos );
// Get the column name
OCIAttrGet((void*) pOciParam, (ub4) OCI_DTYPE_PARAM,(void*) &name,(ub4 *) &len, (ub4) OCI_ATTR_NAME,(OCIError *)pOciError );
// Get the column datatype
OCIAttrGet((void*) pOciParam, (ub4) OCI_DTYPE_PARAM,(void*) &type,(ub4 *)0,(ub4)OCI_ATTR_DATA_TYPE,(OCIError *)pOciError);
// Get the column size
OCIAttrGet((void*) pOciParam, (ub4) OCI_DTYPE_PARAM,(void*) &size,(ub4 *)0,(ub4)OCI_ATTR_DATA_SIZE,(OCIError *)pOciError);
printf("Column %i\tNAME = %.*s \ttype %d \tsize %d\n",pos,len,name,type,size);
// OCIDefine ByPos, one for each parameter
// c_buf store the STATE_CODE, CITY_CODE and CITY_NAME columns from the cursor
rc=OCIDefineByPos(pOciStatCursor,&pdef,(OCIError *)pOciError,pos,c_buf[pos-1],size+1,(ub2)type,(dvoid *)c_indp[pos-1],(ub2 *)0,(ub2 *)0,OCI_DEFAULT);
printf("OCIDefineByPos retval=%d\n,rc);
// call OCIStmtFetch. In the next line, I receive the error
rc=OCIStmtFetch(pOciStatCursor,pOciError,1,OCI_FETCH_NEXT,OCI_DEFAULT);
printf("rc fetch %i",rc);
return 0;
{code} -
Oracle Function returns a Ref Cursor to a ResultSet object - Performance
My program calls an Oracle PL/SQL function which returns a ref cursor to a ResultSet object. I know that the function runs to completion relatively quickly when i run it in an anonymous block but when the call is made through my Java application the resultset takes about 30 mins to return. Below is a snippet of my code:
currentConnection = ConnectionManager.getInstance().getConnection();
reportStmt = currentConnection.prepareCall("BEGIN ? := ENVISION.PKG_WMS_TO_AP.F_REPORT_CI_SC_HOLDING(?,?); END;"); reportStmt.registerOutParameter(1, OracleTypes.CURSOR);
reportStmt.setString(2, invoice.getCrewHQ());
reportStmt.setDate(3, invoice.getWrCompletionDate());
reportStmt.execute();
reportRS = ((OracleCallableStatement) reportStmt).getCursor(1);
Through a debugger I see that the second last statement (reportStmt.execute()) runs quickly. It is only when I step into the last statement that the debugger takes up to 30 minutes.
Any thoughts?Flynn,
The Internet is a dynamic place. After nearly two and a half years, there is a chance that a link will change. This is the new URL for the relevant Web page:
http://asktom.oracle.com/~tkyte/ResultSets/
Good Luck,
Avi. -
Implementing object type methods
I am having some problems with the object type method implementation.
I have poured over the docs and so far they have lead me to a dead end each time.
I am trying to implement a pl/sql object with methods that map to methods in a corresponding java class. The code is as follows:
the java class:
package possystems.poseqdb;
public class ObjTypeCallSpecTest {
private String teststring;
public void mutateString() {
this.testString = "the second value";
the oracle object type:
create type objecttesttype as Object (
teststring varchar2(255),
member procedure objtest as language java
name 'possystems.poseqdb.ObjTypeCallSpecTest.mutateString()'
the anonymous pl/sql block calling the method:
declare
auth1 objecttesttype;
begin
auth1:=objecttesttype('the first string');
dbms_output.put_line('1 '||auth1.teststring||' 1');
auth1.objtest();
dbms_output.put_line('2 '||auth1.teststring||' 2');
end;
There is nothing fancy going on here. The problem I have is the auth1.objtest() call allways returns the following error:
1 the first string 1
declare
ERROR at line 1:
ORA-00932: inconsistent datatypes
ORA-06512: at "ANDRE.OBJECTTESTTYPE", line 0
ORA-06512: at line 6
Note the first line of output is the first dbms_output message indicating the object was properly instantiated.
Could someone please let me know what stupid little thing I have overlooked or have misunderstood from the oracle docs.
Andre>
Use object types as data structures to be manipulated using packages, and ignore the type body possibility.
>
Well that would be throwing away a powerful part of the TYPE functionality.
The methods in the type body can be, and often are, used to provide multi-column validation to prevent the creation of invalid instances. A simple example is an ADDRESS_TYPE (e.g. ADDRESS1, ADDRESS2, CITY, STATE, ZIP) where a valid instance must have a value for each attribute except ADDRESS2 which might be optional.
The constructor and the methods in the body can perform validation to ensure that the components meet certain minimum requirements: not null, length (a 1 byte address wouldn't make much sense), character or numeric content, etc. A SET_ADDRESS1 method can also perform those validations.
That allows instances of those types to be used by PL/SQL code without repeated validation of the attributes. I use such basic TYPEs extensively in ETL and reporting processes. Even something as simple as a TYPE that has FROM_DATE and TO_DATE benefits by having constructor and body methods that prevent the attributes from being NULL and ensure that any TO_DATE is later than the FROM_DATE. -
Passing parameter of object type between Oracle & VB
Hello,
I want to pass parameters of ref cursor type variable between oracle 8i routines and Vb routines. It will be very helpfull for me if you can help in telling me about how to do it.
Regards
Rakesh Banerjee1. On the Oracle side, you may need to do the following:-
(a) define a ref cursor of the desired type in a package specification
(b) define a procedure that returns the ref cursor type as an out parameter, or alternately a function that returns the ref cursor type as a return value.
(c) associate a select statement in the definition of the procedure or function using the synrtax OPEN ref_cursor_name FOR "select XYZ from abc"
(d) compile and debug the package
2. On the VB side one can:-
(a) call the stored procedure or function using the ODBC call syntax for calling stored procedures
(b) bind the output parameter or return value to a resultset variable in VB.
3. The critical step would be using an ODBC driver that supports this syntax and functionality. If the driver available at your site does not work you may need to buy a third party driver that does.
Hope that helps ...
Regards,
Narayan. -
Passing Ref Cursor as IN parameter
I have a situation where I have to send whole table into the stored procedure, I read from the oracle new feature for .Net documentation, It is possible to pass an ref cursor as IN parameter to an stored procedure. Please help me in this, it is urgent!
I am using Visual Studio.Net 2003, ODP.Net.Array binding is the best method for large inserts from .NET.
The problem with the associative array is:
-you must write a PL/SQL procedure to actually do the inserts.
-while this will get the data to the PL/SQL engine on the server in a block, it still must cross the into the SQL engine one row at at time.
-Array binding is simpler (you use a normal insert).
-There's a built-in knob to control the batch size.
-The array of row data is copied all the way into the SQL engine together, so it's faster.
Remember, array binding is how the SQL*Loader's conventional-path inserts work.
According to Tom Kyte "you can achive 100's of rows per second into heavily indexed tables that are concurrently being read and updated by other processes."
David -
Problem in passing ref cursor values as parameter in where clau.Most Urgent
Problem:
1) I have used normal cursor (C_hubmsgid_set) with some select statement such as grouping and all.
After executing the query it will return some resultset to the specified cursor.
2) I am trying to use another cursor which is ref cursor but the problem is
I want to give all the resultset based on all the conditions to the ref cursor.
But the cursor will get only the last record due to overwriting .how to get all
the result set in a ref cursor like
cursor c1 is select .....
loop
open refcursor for
Select * from ....where condition
end loop
After this the refcursor( p_sysaudithistory_cur) which should have all the resultset matched by the where condition.
3. It should be java compatible one.
4. I am not able to match cursor row = IN Pameter value
Below is the query:
CREATE OR REPLACE PROCEDURE SP_TEST_audit_history2 (
p_start IN date,
p_end IN date,
p_msgcode IN varchar2,
p_partnername IN varchar2,
p_status IN varchar2,
p_locationname IN varchar2,
p_custbusunit IN varchar2,
p_sysaudithistory_cur OUT plutotypes.ref_cursor,
p_status1 OUT NUMBER) AS
l_status NUMBER := 0;
CURSOR C_hubmsgid_set IS
SELECT DISTINCT MAX(tfm.datetime) datetime, tfm.hubmsgid
FROM tfm_status tfm, vw_msgcode_part_locn vw
WHERE
tfm.datetime >= NVL(p_start, TO_DATE('01/01/1981','DD/MM/YYYY')) AND
tfm.datetime <= NVL(p_end, TO_DATE('31/12/9999','DD/MM/YYYY')) AND
tfm.msgcode LIKE NVL(p_msgcode,'%') AND
vw.msgcode = tfm.msgcode
AND vw.partnername LIKE NVL(p_partnername,'%')
AND tfm.status LIKE NVL(p_status,'%')
AND vw.locationname LIKE NVL(p_locationname,'%')
AND vw.custbusunit LIKE NVL(p_custbusunit,'%')
AND rownum < 250
GROUP BY tfm.hubmsgid
ORDER BY datetime DESC;
/* Loop through the Cursor */
BEGIN
BEGIN
OPEN p_sysaudithistory_cur
FOR
SELECT
tfm.hubmsgid ,
tfm.status || '-'|| nvl2(tfm.exception_id,'FAILED','OK') ,
tfm.datetime,
tfm.exception_id
FROM tfm_status tfm
WHERE tfm.hubmsgid = c_hubmsgids.hubmsgid /* here only i am getting error*/
AND tfm.datetime = c_hubmsgids.datetime
AND tfm.status like NVL(p_status,'%')
and rownum =1;
EXCEPTION
WHEN NO_DATA_FOUND
THEN
l_status := 1;
END;
p_status1 := l_status;
END;
Thanks in advance
prasanth a.s.Please don't post duplicate questions. All it does is clutter the forums and result in fragmented threads and duplicate responses. Please see my response in the original thread at the link below.
Please solve this Refcursor issue PLEASE -
Problem passing REF CURSOR to JAVA STORED PROCEDURE
Hi,
I've written a small Java class with a static method and
imported that into Oracle 8i. The method expects a
java.sql.ResultSet object as parameter. According to the
documentation of Oracle, a REF CURSOR (cursor variable) maps to
java.sql.ResultSet in JDBC.
The definition of the Java Stored Procedure was accepted without
problems:
CREATE OR REPLACE PROCEDURE RESULTSETPASSINGTESTPROC (row
WASTypes.GenericCurType)
as language java
name 'sqlj.ResultSetPassingTest.testResultSetPassing
(java.sql.ResultSet)';
WASTypes is a package containing the definition of the generic
cursor:
CREATE OR REPLACE PACKAGE WASTYPES
is
TYPE GenericCurType IS REF CURSOR;
END WASTypes;
In a function I'm opening the cursor via
'Open cursorVariable for sqlStatement';
Then this cursor variable is passed to the java method and the
error ORA-03113 is shown.
I tried to solve the problem by changing the type of the
parameter to oracle.sql.REF without success.
Does anybody know what wents wrong?
Thanks in advance.
JanHi,
I've written a small Java class with a static method and
imported that into Oracle 8i. The method expects a
java.sql.ResultSet object as parameter. According to the
documentation of Oracle, a REF CURSOR (cursor variable) maps to
java.sql.ResultSet in JDBC.
The definition of the Java Stored Procedure was accepted without
problems:
CREATE OR REPLACE PROCEDURE RESULTSETPASSINGTESTPROC (row
WASTypes.GenericCurType)
as language java
name 'sqlj.ResultSetPassingTest.testResultSetPassing
(java.sql.ResultSet)';
WASTypes is a package containing the definition of the generic
cursor:
CREATE OR REPLACE PACKAGE WASTYPES
is
TYPE GenericCurType IS REF CURSOR;
END WASTypes;
In a function I'm opening the cursor via
'Open cursorVariable for sqlStatement';
Then this cursor variable is passed to the java method and the
error ORA-03113 is shown.
I tried to solve the problem by changing the type of the
parameter to oracle.sql.REF without success.
Does anybody know what wents wrong?
Thanks in advance.
Jan -
Using a strongly typed ref cursor doesn't enforce data type
I am trying to enforce the datatypes of the fields coming back from an oracle reference cursor by making it strongly typed. However, there seems to be no warning at compile time on the oracle side or exception in ODP.NET if the datatype coming back in the cursor does not match. For example here is my cursor and proc
create or replace
PACKAGE THIRDPARTY AS
type pricing_record is record
BaseIndexRate number(6,5),
BaseIndexRateType VARCHAR2(1 BYTE)
type cur_pricing2 IS ref CURSOR return pricing_record;
PROCEDURE getpricingbyappidtest(appid IN application.intid%TYPE, pricing OUT cur_pricing2);
END THIRDPARTY;
create or replace
PACKAGE BODY THIRDPARTY AS
PROCEDURE getpricingbyappidtest(appid IN application.appid%TYPE, pricing OUT cur_pricing2)
AS
BEGIN
OPEN pricing FOR
SELECT somevarcharfield, someothervarcharfield
FROM application
WHERE A.appid = appid;
END getpricingbyappidtest;
I would expect this wouldn't compile since i am putting a varchar into a number field. But it does. Also if i check the datatype in the reader on the .net side it also is a string. So odp doesn't seem to care what type the cursor is
here is that code and output
var schemaTable = reader.GetSchemaTable();
using (var file = new System.IO.StreamWriter("c:\\_DefinitionMap_" + cursorName + ".txt"))
file.WriteLine("COLUMN" + "\t" + "DATATYPE");
foreach (DataRow myField in schemaTable.Rows)
file.WriteLine(myField["ColumnName"] + "\t" + myField["DataType"]);
COLUMN DATATYPE
BaseIndexRate System.String
BaseIndexRateType System.String
Does anyone have an approach for enforcing datatypes in a ref cursor? Am I doing something wrong when defining the ref cursor?Hello,
By using a ref cursor you are really using a pointer to a cursor. There is no way I know of to make a compile check of the cursor check unless you want to create a SQL type and cast the cursor to this type and even this wouldn't work in all cases. For instance, I could have function call within my cursor select which could return a varchar (with a number always in the varchar) which would be horribly sloppy but legal and you would expect Oracle to compile it.
If you are worried about this I would suggest not using ref cursors and go to UDT instead, where there will be more checking (because of a C# equivalence generated object). Oh and BTW, yes the cursor will throw an exception if the data is incorrect, but only at runtime - just like normal Oracle PLSQL.
Cheers
Rob.
http://www.scnet.com.au -
Pass REF CURSOR to Procedure and LOOP through it
Hi All,
I am trying to figure out how I can pass a ref cursor to a procedure and then loop through it. I have provided an example of what I am attempting to do...just not really sure how to open the ref cursor when it is passed ot the sproc and iterate through it?
Any info would be greatly appreciated.
Version:
Oracle Database 10g Enterprise Edition Release 10.2.0.3.0 - 64bi
PL/SQL Release 10.2.0.3.0 - Production
CORE 10.2.0.3.0 Production
TNS for Linux: Version 10.2.0.3.0 - Production
NLSRTL Version 10.2.0.3.0 - Production
Create Or Replace Package test_ref_pkg
AS
function get_ref_curs
RETURN SYS_REFCURSOR;
procedure process_ref_curs(
p_ref_cursor IN SYS_REFCURSOR
END test_ref_pkg;
Create Or Replace Package Body test_ref_pkg
AS
function get_ref_curs
RETURN SYS_REFCURSOR
IS
l_ref_curs SYS_REFCURSOR;
BEGIN
OPEN l_ref_curs FOR
Select 1 ID, 'Test 1' Name
From DUAL
UNION ALL
Select 2 ID, 'Test 2' Name
From DUAL;
END get_ref_curs;
procedure process_ref_curs(
p_ref_cursor IN SYS_REFCURSOR
IS
BEGIN
---NOT SURE WHAT TO DO TO ITERATE THROUGH THE REF CURSOR I AM PASSING INTO THIS SPROC?----
END process_ref_curs;
END test_ref_pkg;Thanks,
S
Edited by: ScarpacciOne on May 28, 2010 9:11 AM---NOT SURE WHAT TO DO TO ITERATE THROUGH THE REF CURSOR I AM PASSING INTO THIS SPROC?----
-- MAYBE I AM SIMPLE, BUT HOW ABOUT FETCH???
-- if you start to yell, I will yell too!!!!
Sybrand Bakker
Senior Oracle DBA -
Ref cursor to object and return to ref cursor
how i will call object type from refcursor and return value to ref cursor .
I need a help. please help me.
takes oracle object types as input/output.
PROCEDURE createserviceorder(
P_serviceorder IN serviceorder,
P_serviceid in out p_sm_type.serviceid,
P_serviceorderid out p_sm_type.serviceorderid,
Returnstatus out callstatus);
The serviceorder, callstatus are oracle object types.
The wrapper procedure for this API would be something like the example with pseudo code below
PROCEDURE createserviceorderwrapper(
P_serviceorder IN REFCURSOR,
P_serviceid in out p_sm_type.serviceid,
P_serviceorderid out p_sm_type.serviceorderid,
Returnstatus out REFCURSOR)
Map from ref cursor P_serviceorder to oracle object for serviceorder;
Map from other data types to local variables;
Call createserviceorder (pass the parameters here and get output .);
Map output callstatus to its equivalent REF CURSOR variable;
Return callstatus (and other out parameters if any )as REF CURSORS;
} -
Is it possible to pass a ref cursor from java as an input parameter to a stored procedure, which the procedure can then process?
(Passing Ref Cursors as output parameters from a stored procedure to a result set works fine.)You may want to try passing Arrays to the Stored Procedure. Use Oracle.SQL.ARRAY and then in the stored procedure get the array.
-
How to put a collection into a Ref Cursor?
Hi,
I am trying to create a procedure (inside a package) which fills a collection and I need to fill a ref cursor (out parameter) with this collection. I can fill the collection but I how can I fill the ref cursor? I am receiving the message "PL/SQL: ORA-00902: invalid datatype" (Highlighted below as comments)
I have a limitation: I am not allowed to create any kind of objects at the database schema level, so I have to create them inside the package. I'm writting it with SQL Tools 1.4, I'm also not allowed to do this in SQL+.
This is the code of the package. The cursors' selects were simplified just because they are not the problem, but their structure is like follows below.
CREATE OR REPLACE PACKAGE U3.PKG_TESTE AS
TYPE REC_TYPE IS RECORD(
COL1 VARCHAR2(50) ,
COL2 VARCHAR2(100) ,
COL3 VARCHAR2(20) ,
COL4 VARCHAR2(30) ,
COL5 VARCHAR2(100) ,
COL6 VARCHAR2(50) ,
COL7 NUMBER(3) ,
COL8 VARCHAR2(30) ,
COL9 VARCHAR2(16) ,
COL10 VARCHAR2(50) ,
COL11 NUMBER(4) ,
COL12 VARCHAR2(40)
TYPE REC_TYPE_LIST IS TABLE OF REC_TYPE
INDEX BY BINARY_INTEGER;
TYPE C_RESULTSET IS REF CURSOR;
VAR_TAB_TESTE REC_TYPE_LIST;
PROCEDURE Z_REC_INSTANCE
pUSER_SYS_CODE VARCHAR2,
pSYS_SEG_CODE VARCHAR2,
pComplFiltro VARCHAR2,
pCodInter NUMBER,
cResultset out C_RESULTSET
END PKG_TESTE ;
CREATE OR REPLACE PACKAGE BODY U3.PKG_TESTE
AS
PROCEDURE Z_REC_INSTANCE
pUSER_SYS_CODE varchar2,
pSYS_SEG_CODE varchar2,
pComplFiltro varchar2,
pCodInter number
AS
cursor cur1 is
select 'A' COL1, 'B' COL2, 'C' COL3, 'D' COL4, 'E' COL5,
'F' COL6, 'G' COL7, 'H' COL8
FROM DUAL;
regCur1 cur1%rowtype;
cursor cur2 is
SELECT 'I' C1, 'J' C2, 'K' C3, 'L' C4
FROM DUAL;
regCur2 cur2%rowtype;
varSQL varchar2(4000);
varCOL10s varchar2(100);
varFiltroAtrib varchar2(100);
varCount number(10);
BEGIN
varCount := 1;
open cur1;
Loop
fetch cur1 into regCur1;
exit when cur1%notfound;
open cur2;
Loop
fetch cur2 into regCur2;
exit when cur2%notfound;
VAR_TAB_TESTE(varCount).COL1 := regCur1.COL1;
VAR_TAB_TESTE(varCount).COL2 := regCur1.COL2;
VAR_TAB_TESTE(varCount).COL3 := regCur1.COL3;
VAR_TAB_TESTE(varCount).COL4 := regCur1.COL4;
VAR_TAB_TESTE(varCount).COL5 := regCur1.COL5;
VAR_TAB_TESTE(varCount).COL6 := regCur1.COL6;
VAR_TAB_TESTE(varCount).COL7 := regCur1.COL7;
VAR_TAB_TESTE(varCount).COL8 := regCur1.COL8;
VAR_TAB_TESTE(varCount).COL9 := regCur2.C1;
VAR_TAB_TESTE(varCount).COL10 := regCur2.C2;
VAR_TAB_TESTE(varCount).COL11 := regCur2.C3;
VAR_TAB_TESTE(varCount).COL12 := regCur2.C4;
varCount := varCount + 1;
end Loop;
end Loop;
-- I'd like to do something like this:
-- c_resultset := select * from var_tab_teste;
-- but i don't know how to put the records of the type on the ref cursor,
-- probably because I don't know how to select them
-- pl/sql: ora-00902: invalid datatype
for varCount in (select COL1 from table( CAST ( VAR_TAB_TESTE AS REC_TYPE_LIST ) ))
loop
dbms_output.put('WORKS');
end loop;
END Z_REC_INSTANCE;
END PKG_TESTE;
SHOW ERR PACKAGE PKG_TESTE;
SHOW ERR PACKAGE BODY PKG_TESTE;
SHOW ERR PROCEDURE PKG_TESTE.Z_REC_INSTANCE;
I'm using:
Oracle9i Enterprise Edition Release 9.2.0.1.0 - Production
With the Partitioning, OLAP and Oracle Data Mining options
JServer Release 9.2.0.1.0 - Production
Thanks in advance.I don't have the exact version but in 9iOK I lied, I found a 9i instance ;-)
Oracle9i Enterprise Edition Release 9.2.0.7.0 - 64bit Production
JServer Release 9.2.0.7.0 - Production
SQL> CREATE TABLE table_name (column_name VARCHAR2 (30));
Table created.
SQL> INSERT INTO table_name VALUES ('value one');
1 row created.
SQL> INSERT INTO table_name VALUES ('value two');
1 row created.
SQL> COMMIT;
Commit complete.
SQL> CREATE OR REPLACE PACKAGE package_name
2 AS
3 TYPE collection_type_name IS TABLE OF table_name%ROWTYPE;
4
5 FUNCTION function_name
6 RETURN collection_type_name PIPELINED;
7 END package_name;
8 /
Package created.
SQL> CREATE OR REPLACE PACKAGE BODY package_name
2 AS
3 FUNCTION function_name
4 RETURN collection_type_name PIPELINED
5 IS
6 BEGIN
7 FOR record_name IN (SELECT column_name
8 FROM table_name) LOOP
9 PIPE ROW (record_name);
10 END LOOP;
11
12 RETURN;
13 END function_name;
14 END package_name;
15 /
Package body created.
SQL> VARIABLE variable_name REFCURSOR;
SQL> BEGIN
2 OPEN :variable_name FOR
3 SELECT column_name
4 FROM TABLE (package_name.function_name);
5 END;
6 /
PL/SQL procedure successfully completed.
SQL> PRINT variable_name;
COLUMN_NAME
value one
value two
SQL>I recommend though that you test this thoroughly. There were bugs with this approach when it was newly introduced that prevented you from dropping the package. -
Hi,
Is there any way to execute stored procedure via hyperion using ODBC and get back ref cursor data.
I tried to call a stored procedure that have a ref cursor out parameter but it gives me error.
My stored procedure code is below.
wrong number or types of arguments to in call to 'HYP_CURSOR'
create or replace package hyp_ref_cusrsor is
type t_cusror is ref cursor;
end;
create or replace procedure hyp_cursor(ret1 out hyp_ref_cusrsor.t_cusror) is
begin
open ret1 for select * from hyp_tmp1 m;
end;
Hyperion version is 9.3.1
Oracle version is 10.0.2
RegardsGeorge wrote:
Is there a limit to the volume of data a ref cursor can return via an Oracle Database Procedure call? No.
{thread:id=886365}
Re: OPEN cursor for large query
A ref cursor is a pointer to a compiled SQL statement, it has no rows so there is no limit to the number of rows that you can use it to fetch, just like there is no limit to the number of rows a select can return.
I am using a ref cursor to return data and testing using toad, it hangs the session. My Business Object report also hangs because of the large data volume 750,000 rows returned via a ref cursor. This is very confusing, it it hangs how do you know it returns 750,000 rows?
Maybe you are looking for
-
I'm not able to send emails with mail.ru. Receiving is not a problem. Creating a mail is also not a problem and the mail will be stored at mail.ru as still to be send, only problem is its not possible to send. I noticed the buttons for sending change
-
New line character in c:out
hi! I need to print a string in a table , and i am using <c:ForEach> and <c:out> tags to retrieve the data from a session scoped collection. the problem is that i need the data to be printed with new line characters to separate paragraphs, but if i p
-
Hi I have a billing plan type milestone billing assigned to sales order type and item category. I have created date proposal and assigned to billing plan type, In date proposal, there is only one line item, which is closing invoice( i.e 100% of net
-
REP-3000: An internal error occured starting Oracle Toolkit Solaris 10 SPARC
I am running WL 10.3.6.0 with Forms/Reports 11.1.2.1.0 on a Solaris SPARC 10 64-bit box, specifically a T4. Brand new install of Solaris 10 with only Forms/Reports installed as the user "oracle". When I run rwbuilder.sh I get the dreaded REP-3000 err
-
Hi, I have configured mirroring, server A and server B, suppose if server A down, what are the action we need to tak bring up principal server. Thanks in advance Shashikala