Library tutorials & articles
Oracle8 and Oracle8i
Reference Cursors
Oracle has released version 8.1.6 of its own provider, Oracle Provider for OLE DB. This provider has a class name of OraOLEDB.Oracle that is used when defining your ADO connection string. It supports the same set of Oracle data types as Microsoft's OLE DB Provider for Oracle with the additional support for the binary object types BLOB, CLOB, NCLOB, and BFILE, but as with Microsoft's provider, it also does not provide support for the Oracle8i object data types .
This provider gives us pretty much the same level of functionality as Microsoft's, except that it supports the use of Oracle reference cursors so that we can return back an ADO Recordset object from a stored procedure. A reference cursor is a pointer to a memory location that can be passed between different PL/SQL clients, thus allowing query result sets to be passed back and forth between clients.
A reference cursor is a variable type defined using the PL/SQL TYPE statement within an Oracle package, much like a PL/SQL table:
TYPE ref_type_name
IS REF CURSOR RETURN return_type;
Here, ref_type_name is the name given to the type and return_type represents a record in the database. You do not have to specify the return type as this could be used as a general catch-all reference cursor. Such non-restrictive types are known as weak, whereas specifying the return type is restrictive, or strong. The following example uses %ROWTYPE to define a strong return type that represents the record structure of the emp table:
DECLARE TYPE EmpCurType
IS REF CURSOR RETURN emp%ROWTYPE;
So let's jump straight to an example. We'll create a new Oracle package that contains a single procedure, EmployeeSearch, which returns a list of matching employee names. From your SQL editor, execute the following code to create the package specification:
CREATE OR REPLACE PACKAGE
Employee_RefCur_pkg
AS
TYPE empcur IS
REF CURSOR;
PROCEDURE EmployeeSearch(i_EName
IN VARCHAR2,
o_EmpCursor
OUT empcur);
END Employee_RefCur_pkg;
We've created a new type called empcur that returns a weak reference cursor that we use as an output parameter to the EmployeeSearch procedure. Now we need the package body :
CREATE OR REPLACE PACKAGE
BODY Employee_RefCur_pkg
AS
PROCEDURE EmployeeSearch(i_EName
IN VARCHAR2,
o_EmpCursor
OUT empcur)
IS
BEGIN
OPEN
o_EmpCursor
FOR
SELECT emp.empno, emp.ename, emp.job,
emp.sal, dept.dname, dept.loc
FROM emp, dept
WHERE ename LIKE '%' || i_EName
|| '%'
AND emp.deptno = dept.deptno
ORDER BY UPPER(emp.ename);
END EmployeeSearch;
END Employee_RefCur_pkg;
This code is very similar to our previous stored procedure, except that we don't need to transfer each column in distinct PL/SQL tables, as the reference cursor, o_EmpCursor, is returned back to the client. The Oracle Provider for OLE DB converts any parameters that reference cursors into an ADO Recordset for us – but only if we add PLSQLRSet=1 to our connection string, which we'll cover next .
|
Let's have a look at the results page that calls this stored procedure: |
|
The actual ASP is very similar to our
previous example so we'll just concentrate on the sections that
are different :
<%
Dim
strSearchName
Dim
objConnection
Dim
objCommand
Dim
objRecordSet
Dim
objNameParam
Dim
varEmpNo
strSearchName
= Request.Form("txtSearchName")
If
strSearchName = "" Then strSearchName = "%"
Set
objConnection = Server.CreateObject("ADODB.Connection")
So far it's just the same, except that we define a new variable, objNameParam, that we'll use as an ADO Parameter object to pass in the search name entered.
With
objConnection
.ConnectionString = "Provider=OraOLEDB.Oracle;" & _
"Data Source=Oracle8i_dev;"
& _
"User ID=scott;" & _
"Password=tiger;" & _
"PLSQLRSet=1;"
.Open
Response.Write "ADO Provider=" & .Provider & "<P>"
End
With
Here we tell ADO to use the Oracle Provider for OLE DB, OraOLEDB.Oracle, and we set the PLSQLRSet attribute to tell the provider that it should parse the PL/SQL stored procedures to determine if any parameters return a record set. OraOLEDB can only return one recordset per stored procedure. If you call a stored procedure that returns more than one recordset then OraOLEDB will only return the first argument of a ref cursor type.
If you omit the PLSQLRSet attribute, or you set it to 0, then you'll receive the following Oracle error:
ORA-06550: line 1, column
7: PLS-00306: wrong number or types of arguments in call to 'EMPLOYEESEARCH'
ORA-06550: line 1, column 7: PL/SQL: Statement ignored
The rest of the code goes as follows:
Set objCommand = Server.CreateObject("ADODB.Command")
With objCommand
Set .ActiveConnection
= objConnection
.CommandText
= "{call Employee_RefCur_pkg.EmployeeSearch(?)}"
Set objNameParam
= .CreateParameter("SearchName", adBSTR, _
adParamInput, , strSearchName)
.Parameters.Append
objNameParam
Set objRecordSet
= .Execute()
End With
Although our stored procedure has two parameters, the search name and the reference cursor that is returned, you must not bind the reference cursor as a parameter using the ? attribute when using OraOLEDB, so we've included only one ? character to represent the Name input parameter .
The ADO Parameter object, objNameParam, is created using the Command object's CreateParameter function. CreateParameter is called in the following way:
Set parameter = command.CreateParameter(Name,
Type, Direction, Size, Value)
objNameParam is declared as an adBSTR type because this maps to Oracle's VARCHAR2 data type. Once we've created the Parameter we need to add it to the Command object's Parameters collection using the Append method .
Finally we call the Execute function to return a Recordset object that represents the result set from the o_EmpCursor reference cursor parameter. That's all there is to it. We can then navigate through the Recordset object as usual.
It's worth remembering that if you try
to call the stored procedure using the Parameters
collection directly:
.CommandText
= "{call Employee_RefCur_pkg.EmployeeSearch(?)}"
.Parameters(0).Type
= adBSTR
.Parameters(0).Direction
= adParamInput
.Parameters(0).Value
= strSearchName
you'll get the following runtime error:
The provider cannot
derive parameter info and SetParameterInfo has not been called
Therefore you must use the CreateParameter function.
That wraps up our look at retrieving ADO Recordset objects from Oracle stored procedures. As you've seen, we have two choices: PL/SQL tables with the Microsoft ODBC for Oracle Driver or reference cursors with Oracle's Oracle Provider for OLE DB. On the face of it, the use of PL/SQL tables does appear rather convoluted in comparison to the ease of reference cursors. Both are relatively inefficient in terms of server performance and the Oracle Provider for OLE DB has been regarded as rather buggy. Again, it's your choice; it's difficult to define what each can and can't do. As ever, you should investigate how both methods perform in your own environment, looking at response times along with CPU and memory usage.
Related articles
Related discussion
-
Key_Press() event for text box
by Aquila (1 replies)
-
how to select multiple files at a time using Ctrl+select and upload the attachments in C# .Net 1.0?
by vasanta (0 replies)
-
Regarding Visual Basic Programme
by manjunathsl2007 (0 replies)
-
how do you hide all in VB6
by CapnJack (1 replies)
-
Problem with Input File
by novavb6 (3 replies)
Related podcasts
-
Java Posse #213 - Newscast for Oct 23rd 2008
Newscast for Oct 23rd 2008 Fully formatted shownotes can always be found at http://javaposse.com The Android project has been released as open source, beating the rumored launch date for the source code by several months http://source.android.com/ And, Gizmodo and ZDNet both offer in-depth ...
How can I create a master detail web form using ASP, ADO, vbscript, and HTML?jarvis@anteon.com">email me
Hi all,
I've been trying to use the OLE DB connection from ASP to Oracle. Used the code from the examples. Working fine but it did not release the session connection and when the sessions reach the maximum defined, it will fail to work. Pls Help. Thank you.
KK
Hi,
I using .NET to access Oracle DB (with OLEDB Provider for Oracle) but I have a trouble that I couldn't use Unicode datatype (such as: NCHAR, NVARCHAR2).
Anyone knows how to do this or any Provider that allows us access Oracle DB with Unicode datatype?
Thanks for you kindness.
TCAN.
im trying to get this to work:
when the form loads, a csv file is opened and whose contents are displayed in the Current list view control. if the user selects an item from the Current listview control and presses the "delete" key (i've been using the Keypress event), a message box will pop up asking them to confirm their decision. If they say yes, the entire row is cleared and that row's information is passed to another listview control (the Archives listview control, which is saved onto its own file)
the main things i need to know are the ASCII code for the delete key (127 doesn't work...), and how to delete an entire row in a listview control (and the other records below it should be moved up as a result.) If you could tell me how to then pass it onto the second listview control as well, that would be greatly appreciated.
thanks in advance
Hi,
i am currently do a project on oracle and microsoft. The question is compare and contrast the latest database offerings from Oracle and Microsoft under the following headings: History and evolution of the products, Target Market, Functionality, Customers, Future Directions, and any other areas. Any inforamton would be appreciated
Hi ,
I'm using resultset in oracle and vbscript as it was mentioned here as follow:
create a package that return a ref cursor,execute the package in vbscript and get the resultset into the
recordset .
Sometime it works and othertime I get that error in the line when I call the execute to the procedure:
OraOLEDB error '80004005'
Unspecified error .
I used the example you gave in page :http://www.developerfusion.com/show/671/12/
Please help me
This thread is for discussions of Oracle8 and Oracle8i.