This site has been taken over by the staff of www.ASPDeveloper.Net

Please report errors to suggest@aspdeveloper.net

BizTalk Utilities CV ,   Jobs ,   Code library  
 
 

Washington, September 15-18, 1999 – London, November 21-24, 1999

VB and Oracle

Dov Trietsch

Introduction

Oracle is the No. 1 provider of relational database software, and many of my clients use it in conjunction with VB. Just before I sat down to write these lines I browsed the sites of two major job exchanges, looking for VB and VB + Oracle jobs in the NY metro area. There are hundreds of jobs out there with better than 35% of them requiring the dual skill (285/797) in one site and (146/414) in the other. Yet there are hardly any books and articles dealing with the combination. Obviously we are doing something about it today.

These notes reflect the content of my presentation. This, unfortunately, is a very short session so, at times, I'll be too brief. Please bear with me.

Dov Trietsch
Dov Trietsch has been a professional Programmer/Analyst for over thirty nonconsecutive years. The break in the continuum happened when he was demoted to VP of a life insurance company. He is still trying to make up for this transgression. He has been involved in many forms of data storage and retrieval systems culminating in RDB in general and Oracle in particular. He's the principal of Megasolutions - A small Systems Consultancy. He keeps himself at the forefront of the technology by a relentless pursuit of self-education, which leaves little time for his favorite pastimes of theater, music, and fine literature. When not writing, learning, or vacationing, he helps his clients to build web-enabled applications using VB, VBScript, Oracle, IIS, ASP, MTS, Java Script, and ADO. He is the author of a soon to be published Wrox Press Programmer's reference to VB and Oracle. Dov can be contacted at coachcs@aol.com.

Why Oracle?

35% of the VB jobs advertised is reason enough. But there's more!

Ø        Oracle is the No 1 purveyor of RDB. At least 40% of the Fortune 100 use it more than any other brand.

Ø        Oracle is available on every shade of OS. NT, Unix and Mainframe.

Ø        This means SCALABILITY to the utmost

Ø        It is the fastest DB on most (some say every one) of these platforms.

Ø        It is a most reliable RDB

Why VB?

We're VB programmers and we love it!

Connecting to Oracle

Now that we know why we're here, let us get into the nitty-gritty details. First how do we connect to an Oracle database?

As you can see in the diagram, this presentation concentrates on just three of the available methods, namely: ADO through ODBC, ADO through the OLE DB, and Oracle Objects For OLE.

OLE DB

Many of my clients use ADO to talk to their databases. They claim that they enjoy greater flexibility with ADO. Should they ever want to switch from Oracle, they will have less code to convert. The relative ease of conversion is a pipe dream, but it is true that we'll convert our VB pieces somewhat faster using ADO. We can use ODBC or OLE DB as the ADO conduits. The difference between the way we connect using either of them is minute. The speed of the connection is a different matter altogether. Going through OLE DB will cut the connect time in half.

Public Sub OpenConnection(sDB As String, sUser As String, sPW As String)

   

    msConnect = "Provider=MSDAORA.1;" & "Password=" & _

        sPW & ";User ID=" & sUser & ";Data Source=" & _

        sDB & "; Persist Security Info=True"

   

    Set mADOConnection = New ADODB.Connection

                                   'Let's instantiate the object!

    With mADOConnection

        .ConnectionString = msConnect

        .ConnectionTimeout = 10

        .CursorLocation = adUseNone

        .Open

    End With

End Sub

The code that you see here highlights the connect-string for OLE DB. It is actually a part of the 'OpenConnection' public method in my homegrown connection class. Let's see how the same lines differ for ODBC.

Public Sub OpenConnection(sDSN As String, sUser As String, sPW As String)

   

    msConnect = "Data Source=" & msDSN & ";User ID=" & _

    msUser & ";Password=" & msPW & ";"

   

    Set mADOConnection = New ADODB.Connection 

                                   'Let's instantiate the object!

    With mADOConnection

         .ConnectionString = msConnect

         .ConnectionTimeout = 10

         .CursorLocation = adUseNone

         .Open

    End With

End Sub

ODBC

Just a few weeks ago, I was asked to write a batch program for a client. They receive membership information from clients and load it into an online database. They wanted the job done using ADO and ODBC. We had one little problem. At first the program was loaded on one desk and I've added a system DSN to that desk to match the system DSN in my connect string. The client later decided to install the program, on the fly, on many other desks. Loading the program was easy, they simply copied it from the network drive, but we still had to create the new system DSN on each desk. Many of the desks had pre-existing system DSNs, only they used a variety of different names. I solved the problem by creating a VB Class that finds the Oracle system DSN in the Registry, and uses it in the connection. Now it is much easier to distribute the program. Here is how the class is used.

Private cConnection As clsConnection

'We're interested only in the OpenConnection Method

Private cBlob As clsBlob 'just another data class

Private Sub cmdOK_Click()

    Dim sDSN As String

    Dim cDSN As New clsDSN

    Set cConnection = New clsConnection

    sDSN = cDSN.FindDSN(DBName)

    If sDSN = "DB Name not found!!" Then

       MsgBox "You don't have a System DSN to the requested Database.

                Please call the helpdesk!"

        End

    End If

    cConnection.OpenConnection sDSN, sUser, sPW

    Set cBlob = New clsBlob

    cBlob.Connect cConnection

End Sub

I've written a sample program as a demonstration of this named DSN.vbp (and frmDSN.frm). I have since used this object and method on the site of a second client. A copy of the code is included on the Conference CD.

The last method of connecting to Oracle is using 0040. We'll cover this method in a few minutes as a part of a general introduction to 0040. But first let's see some of the features unique to the Oracle database.

Oracle – The Data Dictionary, DUAL, and Rownum = 1

Oracle contains one general-purpose dummy table – DUAL. You use DUAL as the dummy table when you want to get information such as SYSDATE, which is the Date and Time, in the Oracle Server (as opposed to the Network server or your personal computer).

During the presentation, I demonstrate running the next two SQL statements in SQL*PLUS while explaining how they work. However, this and other demonstrations require the Oracle Engine that can't be distributed.

SELECT SYSDATE FROM DUAL;

You may also use DUAL to get sequence information and to advance a sequence to its next value.

SELECT Sequence_Name NEXTVAL AS BIG_NUMBER FROM DUAL;

Will advance the sequence by its increment and return the result in the ALIAS BIG_NUMBER.

Using ROWNUM = 1 is another trick. When I use an ADO or 0040 Resultset (dynaset) only to add rows to a table, I do the Rownum trick. Every row in every table has an implied Rownum. It is 1 for the first row in the table, 2 for the next and so on. Because a recordset is defined by its select statement, and because we really don't care which row we get before we add a new one, we use ROWNUM = 1 as the selection criterion. This, BTW, gives us an opportunity to see that ADO with Oracle looks almost like ADO with anything else.

Set objConnection = New ADODB.Connection

   

objConnection.Open sDSN, sUSER_ID, sPASSWORD

   

sSQL = "Select Column1, " & _

            "Column2, " & _

            "Column3 " & _

            "FROM Table1 " & _

            "WHERE rownum = 1"

   

Set objRecordset = New ADODB.Recordset

objRecordset.Open sSQL, objConnection, adOpenDynamic, adLockOptimistic

objRecordset.AddNew

    objRecordset("Column1") = NewValue1

    objRecordset("Column2") = NewValue2

    objRecordset("Column3") = NewValue3

objRecordset.Update

Finally let's inspect the Oracle Data dictionary.

The Oracle SQL*PLUS window can be difficult, at times. You may try running, for example, a long query - this results in a flurry of activity with lines flying across the screen - it's difficult to see much of what's happening. I prefer a more controllable environment, where editing is easier and we enjoy better control of the screen. One cannot avoid SQL*PLUS altogether and most of the time it is pleasant enough. It is, however, too unforgiving. It was built for a printing terminal such as a Teletype machine and it is difficult to cut, paste and edit on the line itself. I keep my 'scripts' in '.txt' files where I edit and then just paste the results into the Oracle command line. I also built a very simple tool using VB and the Oracle Data Control. The very same query now looks quite different. See the code example oraView.vbp (and frmView.frm + the required frmView.frx)

 

Voila! The program is made of a single form and a few lines of code. Most of these are just adding items to a listbox. We'll get back to this program when we discuss the ODC. For now, let's see how we can learn about Oracle's Data Dictionary using this program.

The Oracle data dictionary is a special set of tables that reside in the database itself. These are read only tables. These tables get updated by the system whenever the tables, sequences, etc. are changed The DBA can change them at will, but a smart one does not! Users can only see the objects in their own schema. Finally, here they are:

Ø        USER_OBJECTS - where all the objects are listed and described

Ø        USER_TABLES - where the tables are described

Ø        USER_TAB_COLUMNS - where the columns are described

Ø        USER_SOURCE - where code for stored procedures is held

Ø        USER_SEQUENCES - where all the Sequences are described

Ø        A sequence is a persistent counter that is “upped” every time it is used. It is usually used for creating unique keys.

Ø        USER_ROLE_PRIVS - Oracle allows the DBA to assign various users different roles. A role is a set of permissions or privileges that the user has. One user may only be able to SELECT or read a few tables, another may also be able to UPDATE a few tables. The privileges are given as a list of tables and actions. The actions are SELECT, UPDATE, INSERT, and DELETE. Each user may have many roles. The DBA has unlimited privileges over all the tables in the database. Each user (if he or she is SQL savvy) can "see" his roles and their privileges in the USER_ROLE_PRIVS. Many programs are written to behave according to the role the user assumes. Such programs benefit from the ability to read this table.

Have a go through the program and view these structures in a standard DBGrid using oraView.vbp.

 

With user objects, we're mainly interested in the OBJECT_NAME, and OBJECT_TYPE columns. You can see all the tables listed in USER_TABLES.

USER_TAB_COLUMNS is where the mother lode is found! COLUMN_NAMEs, DATA_TYPEs, DATA_LENGTH, DATA_PRECISION, and DATA_SCALE. Precision and scale apply to numeric columns. You'll note that the data length of numeric columns is a constant 22. The precision determines the total number of digits you'll get and the scale is the number of decimal places. 8 and 2 mean a total of 8 digits, 2 of which are after the decimal point.

A copy of the code for this program is included on the Conference CD.

The information in USER_TAB_COLUMNS may easily be viewed inside SQL*PLUS by using the DESC command.

When we want to write programs that massage the data dynamically we use the data dictionary inside ADO or 0040. DESC, because it is not a DML statement, does not work in ADO or 0040. We can also look in the Fields collection of a Resultset, but only after the Resultset has been defined by its SELECT statement. Using the data dictionary allows us to investigate the structure beforehand. Take a look at the data classes for USER_TABLES and USER_TAB_COLUMNS. The code you see is used inside my own data class generator. It uses 0040 to read the data dictionary and it generates 0040 code. This is a good time to dive into 0040.

Oracle Object For OLE (0040)

Ever wondered why it is nicknamed 0040? These are the initials of Oracle Objects 4 OLE! I've highlighted 6 of the 9 objects in the model. These are really important because that's where we do all programming. Let's dispense with the less important pieces first.

OraClient is just a figurehead. Its purpose is merely to contain the OraSession. It has no properties or methods that are exposed to the programmer. This means that there is nothing we can do to change its behavior. OraClient represents the OracleInProcessServer, which is introduced at the project level. In your project menu click on the references and select the OracleInProcessServer by clicking on its checkbox. That's it! Your project now includes an OraClient.

OraConnection is automatically created when we make an OraSession object, and serves no other unique purpose. This, as we have already seen, is not the case with ADO.

OraParameterArray is the smart manner by which 0040 passes multiple parameters to the server. Sadly, we do not have time to devote to this here.

And now for the more important Objects...

OraSession – when a user ‘talks’ to an Oracle database, the conversation takes place in a session. This is the real root of Objects for OLE. A session implies that the user’s computer is connected to the Oracle server. We only need two lines of code to make a session. The lines below were copied from clsConnection - a class that I include in all my VB and Oracle Projects, and which will be discussed at somewhat greater length later.

Private mOraSession As OraSession

Set mOraSession = CreateObject("OracleInProcServer.XOraSession")

The table below shows the important methods of the OraSession object. Four of the five methods in the table deal with Transactions.

Method

Description

BeginTrans

Begins a Transaction - see below

CommitTrans

Commits a Transaction

OpenDatabase

Uses a DatabaseName, ConnectString and Options to open a Database

ResetTrans

Indiscriminately cancels all open transactions - use very carefully!

Rollback

Cancels a transaction

A Transaction is a very important concept. Think about what happens when you transfer money from your savings account to your checking account. First the balance in your savings is reduced, and then your checking balance is increased. This, by the way, is the order in which the bank prefers to do the transfer. Should the process fail midway, you end up short. But I digress. It would be much better if we could guarantee that the transfer is completely done or not at all. This is where Transactions help. Every relational database has a transaction mechanism that starts with the BeginTrans command and ends with a CommitTrans or a Rollback. We commit the transaction if all went well (no errors were encountered) or roll it back if we encounter an error.

Using transactions is mandatory whenever you update more than a single row at a time - even if the rows are in the same table.

The most important OraSession method is OpenDatabase. We need to open a database in order to be able to work with it. In the presentation, I shall demonstrate how clsConnection does it in detail. I have built an application generator that uses 0040. I intend to demonstrate how we can design a table and maintain it in VB, all in 5 minutes. I do not distribute the generator in source code form. The exe requires Oracle to run. I attach the .exe - DBClassGenerate.exe. I’ll then talk about two files; clsConnection.cls and clsUserColumns.cls.

The DatabaseName, User, and Password are properties of the class, each with its Property Let. I normally use a SignOn form that passes the user entered values to the class. I construct the connect-string, from the user name followed by a slash and the password, and pass it to the OpenDatabase method.

The last parameter in the OpenDatabase method is the database Options parameter. These options are explained in the table below. Note that each constant used in 0040 has been given a descriptive name. These names are included in the ORACONST.txt file that comes with the Oracle 0040 installation disk. I include them in a standard VB module as constants. Because the code in the clsConnection is written once and used forever, and because I prefer short lines of code, I put these options as numbers rather than descriptive constants. You may opt to go the other way. Be that as it may, here, at last, are the values:

Value

Constant

Description

0

ORADB_DEFAULT

VB mode. Field (column) values not explicitly set are set to NULL when using AddNew or Edit. The NULL values override any server column defaults.

1

ORADB_ORAMODE

Oracle Mode. Let Oracle database set the default field (column) values when using AddNew or Edit. The Oracle default column values are refetched from database immediately after the insert or add. This mode allows the program to do successive edits without encountering error 4119.

2

ORADB_NOWAIT

Turns off waiting on rowlocks. When you use Edit to update a row that is locked by another user or process, Lock No Wait mode results in an immediate return of an error code (ORA 54).

4

ORADB_NO_REFETCH

Like ORAMODE, but data is not re-fetched to the local cache, boosting performance. I'm against this option. It is designed to work with programs that only AddNew rows to a table, but most systems mostly read data and only occasionally write it out. It is better to use Parameter Arrays in OraSQLStmt for 'Add Only' programs.

8

ORADB_NONBLK

Not important. Only for 16 bit systems (Win 3.1)

OraDatabase

The Database is where it all happens. This is where we store data and where we retrieve it. It is the Raison D'être of this lecture. The center of the OraDatabase object is the OraDynaset around which we build the various Data Classes. The creation of dynasets is the most important method in 0040, but also the most elaborate. I save it for last. Here are the Oradatabase properties. Most are superfluous, one should be avoided, and three are useful.

Property Name

Description

Connect

Returns the ConnectString - User/Password. This is a very dangerous property. The only use I have for it is breach of security. The availability of such dangerous items is one of the reasons I encapsulate the Database as a PRIVATE object in the clsConnection.

DatabaseName

Ditto! As if the programmer does not already know the Database name. Useless, but at least not dangerous.

Connection

Returns the oracle connection object - actually a pointer thereof. Another useless, harmless property.

RDBMSVersion

Returns the DB version, i.e 8.0.4 (hot stuff!)

Options

Returns the options you've just set with the OpenDatabase method of the OraSession. How could I survive without it?!

LastServerErr

Contains the last non-zero error number returned from the database. Use this, and the next two properties, to check for errors.

LastServerErrPos

Contains the position (character number) of the error in your SQL

LastServerErrText

Contains the description of the last server error

Parameters

Parameters are the equivalent of SQL statement variables. We create them using a Database method.

The LastServerErr, LastServerErrPos, and LastServerErrText go hand in hand in hand with the LastServerErrReset method of the OraDatabase. They give us the error number, the position in the SQL string where the error occurred, and the Oracle error text.

Parameters are actually placeholders inside SQL statements. They belong to the database and not to any particular dynaset. In the following SQL statement ‘IdField’ is a parameter, and can be identified as such by the preceding colon (which is the equivalent of ADO's '?'.

The advantage of using parameters is that we do not have to re-issue a SQL statement with every change in the UserId. We may simply assign a new value to IdField and rerun the existing statement (which is done by issuing the Refresh command to the dynaset – Dynaset.Refresh). SQL statements can be compiled in the database. Compiling makes them run faster because we save the time it takes to interpret them again and again. The compiled statements are our Static SQL, as opposed to the constantly interpreted Dynamic SQL. Using parameters increases performance and also eases our programming effort.

Here are the OraDatabase Methods.

Method Name

Description

Close

The OraDatabase object always closes the database when the object terminates. The 'Close' method was included solely for VB compatibility. Skip it!

CreateDynaset

This and the next 3 methods are the mother lode. We create dynasets - updatable views - in which we perform database maintenance.

CreateCustomDynaset

My preferred method of creating dynasets. You can fine-tune its performance and memory requirements.

CreatePLSQLDynaset

Creates a dynaset around a PL/SQL cursor. This method is no longer available in 3.0.

CreatePLSQLCustomDynaset

Ditto, only fine tunable.

CreateSQL

Creates the OraSqlStmt object. Equivalent to ADO.Command

ExecuteSQL

Executes an SQL Statement upon request. It is more efficient to execute a statement inside an OraSQLstmt object.

LastServerErrReset

After you've read and acted upon server errors, use this method to clear them. This is important, because the server does not send us an OK, or error 0 message. The error you get (unless you reset) may be from yesteryear.

We only have time to discuss a couple of these methods. Here they are:

LastServerErrReset

The most important piece of any data object is the Recordset. In 0040 it is still named Dynaset.

CreateDynaset

A select statement produces a view. Views have rows and columns and are, therefore, virtual tables. The early Microsoft name for such a view was a snapshot. You could look at it to your hearts delight, but you couldn't change it. A dynaset is a view that allows you to change its contents. It is a snapshot with a photo editor. Better still, while a photo editor allows you to change the photo, the dynaset allows you to change the landscape itself. Any change you introduce to the dynaset is immediately reflected in the underlying database. This is true for all dynasets that are based on a single table. Changing values in dynasets that result from more complex searches, such as Joins would be very difficult if not impossible, and they are read-only!

Dynasets are the equivalent of RDO's Resultsets and ADO's Recordsets.

Here is how we create a dynaset in 0040.

Set mOraDynaset = mOradatabase.CreateDynaset (sSQL, Options)

The method has two arguments (or parameters):

Ø        sSQL – A SELECT statement. This statement, unlike standard SQL statements, must not end with a semicolon. 0040 inserts the semicolon.

Ø       Options – A long integer that assumes any combination (sum) of the following:

 

Value

Constant

Description

0

ORADYN_DEFAULT

Much like the ORADB_DEFAULT, with this setting, the values not explicitly set in an Edit or AddNew are inserted as Nulls. This may cause problems because of subsequent 4119 errors. I always use option 16 (ORADYN_ORAMODE).

1

ORADYN_NO_AUTOBIND

Use only if your SQL has no parameters. Mine almost always do, so 1 in not an option for me.

2

ORADYN_NO_BLANKSTRIP

The dynaset normally strips trailing blanks from character fields. This option leaves the trailing blanks in. I don’t see why it is so important.

4

ORADYN_READONLY

Many times you use dynasets just as hinges to other dynasets. If you don’t intend to update the records, open the dynaset for read only. It will run much faster.

8

ORADYN_NOCACHE

With this option, because only one record is held in memory, you can do only forward movement (MoveNext, but no MovePrevious), but you get faster results. I don’t use the option much and skip it in this book.

16

ORADYN_ORAMODE

With this option, because columns not specifically set in an Edit or AddNew get the Database defaults, and because the dynaset is refreshed with the actual Database values after such updates, I achieve my goals with the least amount of 4119 headaches. I still get 4119’s if another user changed data while I contemplated my change, which is the way it should be.

32

ORADYN_NO_REFETCH

Same as 16, but without refreshing updated values. I avoid it.

64

ORADYN_NO_MOVEFIRST

The dynaset is unpopulated. Useful when you only intend to insert new rows. I haven’t used it yet!

128

ORADYN_DIRTY_WRITE

Do not ever use this!! It was invented to avoid error 4119 in very busy databases, but actually allows you to rewrite over previously updated information with impunity. Dangerous to the health of your data.

As you surmised from the way I described the options, I only use option 4 or option 16. The two are obviously mutually exclusive. When I only need to read data I use 4, otherwise I use option 16.

OraDynaset

Covering all the OraDynaset properties and methods is an arduous undertaking. It is also not necessary. Most are hardly ever used. I’ll talk about four properties. You can review the rest in the 0040 help file.

Property

Description

BOF

True or False. True if you have moved to before the first record in the set.

BookMark

A String that uniquely identifies a row in the Dynaset.

Fields

The collection of all the fields in the SELECT Statement that was used to create the dynaset. A collection of OraField Objects. This collection has one important property of its own – Count. Fields may be accessed by name or by their index (0 to Count – 1).

LastModified

A Bookmark of the row that was last modified. When the AddNew, or the Edit method is applied this value changes and points to the last row updated or added.

EOF

True or False. True if you have moved after the last record in the set.

RecordCount

Returns the number of records in the dynaset. Unlike RDO, you don’t need to MoveLast before you count unless this is a dynaset that was created with the ORADYN_NOCACHE option. Then the MoveLast will be done implicitly. Be careful because this will cause the last record to become the current record.

RowPosition

Each row in an Oracle table has a rownum. RowPosition is the rownum of the current dynaset record.

SQL

The SELECT statement that defined the dynaset.

Transactions

Boolean. A dummy property that always returns True. Don’t use this!

Updatable

Boolean. Only single table dynasets can be updateable, and only if opened for read-write (not Read-Only). Even then, the dynaset may not be updateable because the user lacks the right privileges.

NoMatch

Boolean. True if the last find method did not find a matching record. See the Find Methods below for detail.

An empty dynaset –when there are no records matching the query - returns both EOF and BOF as true.

And here are a few of the OraDynaset methods.

Method

Description

AddNew

Adds a new record to a table. Actual database update will happen only upon using the Update method. Equivalent to the INSERT SQL statement.

Delete

Deletes the table row corresponding to the current dynaset record.

Edit

Applies changes to the current dynaset record into the proper table row. Equivalent to the UPDATE SQL statement. Actual database update will happen only upon using the Update method. Edit locks the record in the database. It can only be released by an Update.

‘Find’ methods

The following four methods are unique to 0040. They have no equivalents in DAO, RDO or ADO. 0040 can do a cache search for conditions you preset in a Find Clause which is any valid SQL WHERE clause without the 'WHERE'. Because this is 0040, you can use Oracle functions in the ‘Find’ condition.

FindFirst

Finds the first occurrence, if any, of the FindClause. If there is no match, the ‘NoMatch’ property of the dynaset is set to True. If NoMatch, you’ll remain at your current record.

FindNext

Finds the Next occurrence, if any, of the FindClause. If there is no match, the ‘NoMatch’ property of the dynaset is set to True. If NoMatch, you’ll remain at your current record.

FindLast

Finds the Last occurrence, if any, of the FindClause. If there is no match, the ‘NoMatch’ property of the dynaset is set to True. If NoMatch, you’ll remain at your current record.

FindPrevious

Finds the Previous occurrence, if any, of the FindClause. If there is no match, the ‘NoMatch’ property of the dynaset is set to True. If NoMatch, you’ll remain at your current record.

‘Move’ methods

The following 4 methods are similar to the ADO, DAO and RDO methods. You must check for EOF and BOF before moving.

MoveFirst

Moves to the first record in the set, if any.

MoveLast

Moves to the last record in the set, if any. MoveLast forces the dynaset to complete the query. Use MoveLast before checking the RecordCount property.

MoveNext

Moves to the next record. Moving Next from the EOF causes an error.

MovePrevious

Moves to the Previous record. Moving Previous from the BOF causes an error.

MoveNextn

Allows you to move more than a single position forward. If the move brings you beyond the last record, the dynaset will be positioned on the last record and EOF will be True. Allows only a positive parameter. I hardly ever use it.

MovePreviousn

Allows you to move more than a single position backward. If the move brings you beyond the 1st record, the dynaset will be positioned on the 1st record and BOF will be True. Allows only a positive parameter. I hardly ever use it.

MoveRel

Allows positive (to move forwards) and negative (to move backwards) parameter. Sets EOF and BOF as needed. I hardly ever use it.

MoveTo

MoveTo 1 will go to the first record. MoveTo 5 to the fifth. Check the RecordCount property before you use it. I hardly ever use this method.

Refresh

Runs the SELECT statement again and reloads the dynaset. Use it sparingly.

Update

Edit and AddNew only change the array of records in the dynaset. Update cements the content in the database. It releases the lock that started with the Edit.

Last but not least, the OraDynaset has a built-in collection of fields. The fields correspond to the names of the columns in the underlying SELECT statement. These fields are referenced in the code rather frequently. The syntax for referencing a field is as follows:

Xyz = mdynTestDemo.Fields!FIELD_1.Value or

Xyz = mdynTestDemo.Fields(“FIELD_1”).Value

To assign a new value to the field:

mdynTestDemo.Fields!FIELD_1.Value = xyz

Use Early binding:

Private mfldField1 As OraField

Set mfldField1 = mdynTestDemo.Fields!FIELD_1

Xyz = MfldField1

MfldField1 = xyz

Use early binding for fields and parameters, whenever possible!

OraSQLStmt

At times we need to execute SQL statements from the OraDatabase object. The simple way is to use the OraDatabase.ExecuteSQL(SQL) method. For SQL statements that are executed more than once, use the OraSQLStmt object where the SQL statement is compiled the first time it is used. Each additional usage is done with Oracle p-code, making it much faster. The SQL statement may be a stored procedure and may include parameters. The statement is not limited to 'SELECT' and is used most of the time for action queries (UPDATE, INSERT, DELETE). To execute the statement from within the OraSQLStmt we invoke the Refresh method. Executing SQL statements directly or in the OraSQLStmt causes an automatic Commit. This can cause problems if complex transactions are executed in the background. For this reason, we must use the OraSession.BeginTrans method before running any SQL. This not only improves safety, but also boosts performance.

We create an OraSQLStmt object by:

Private mMyQuery As OraSQLStmt

Set mMyQuery = OraDatabase.CreateSQL(sSQL, Options)

mMyQuery.Refresh

Using a stored procedure:

Here is how we use a stored procedure. Note that here the SQL statement is enclosed in a Begin-End structure and that the semicolon is used.

mOraDatabase.Parameters.Add "Param1", Space(40), 1

mOraDatabase.Parameters.Add "Param2", Space(35), 1

'The next two parameters are output and thus the 2

mOraDatabase.Parameters.Add "ErrNum", 0, 2

'The 0 is the value of the number

mOraDatabase.Parameters.Add "ErrText", Space(50), 2

SSQL = "Begin proct_name(:Param1, :Param2, :ErrNum, :ErrText); end;"

mOraDatabase.Parameters("Param1").Value = NewValue

mMyQuery.Refresh

lErr = mOraDatabase.Parameters("ErrNum").Value

If lErr <> 0 Then

    sErr = mOraDatabase.Parameters("ErrText").Value

    MsgBox CStr(lErr) & sErr, "Can't Update Name"

End If

Options are 1 to stop parameter binding and 2 to raise an error if the SQL statement is invalid. Option 2 is the option I regularly use. I haven't yet used a SQL without parameters in an OraSQLStmt object. I also have yet to use a parameter-less stored procedure. The most common use of an OraSQLStmt is to run a stored procedure.

The Oracle Data Control

The ODC is a standard bound data control. It behaves exactly like a standard data control. The connection string is that of 0040 and the SQL statement defines a Dynaset inside the control. All the standard 'move' methods apply, as do the AddNew, Delete, and Update. The OraStruct program that we've viewed before, and for which you have received the source code, goes on to bind the ODC to a standard grid. The fastest way to create a simple Oracle VB program is using RDC this way.

I wish I could devote more time to 0040. Companies who are committed to using Oracle should try it. Those who do, find it an excellent tool. I want to use the remaining time to go back to ADO.

ADO all over again!

I have printed the connection class for ADO as well as a data class. Most of what you're going to see is mundane ADO code. I am using a parameterized SQL statement to read the database and an ADO.Command with parameters to update the very same table.

The one place where we have to be very careful when doing ADO with Oracle is in declaring parameters. You must be very careful to declare parameters for VARCHAR2 columns with the maximal length. Date/Time parameters are declared with the adDBTimeStamp constant. Any parameter that does not match the length of the column in Oracle will be flagged and cause a runtime error.

Take a look through the two classes clsSmpconnection.cls and clsSample.cls for further info.

Back to 0040

You can consider this a "Try it Out". Go to SQL*PLUS and create a new table. Go to VB and run my generator (DBClassGenerate.exe) on this table. The result is a short program, which you'll be able to use on the spot. The entire process should only take you about 10 minutes.

Oracle and Access

There is still another way to connect to oracle. This is especially important to power users who understand the basics of RDB and can work in Microsoft Access.

We already have a system DSN to Oracle. We can use this ODBC connection from within Access. All you need to do is to link access to the oracle tables of interest. You may now view them and update them from within Access. This gives the power user an almost instant access (pun intended) to Oracle.

0040 and ADO – What shall I use

It is a tough decision. ADO seems to be the standard and we all love to join the crowd. William Golding was once asked by his then fiancée (she soon left him), why he should not become a Methodist like her and her Minister father. “There are millions of Methodists” she claimed, “how could all of them be wrong?” Golding replied that there are even more Buddhists so how could all of them be wrong. But I digress.

ADO and Oracle were not exactly made for each other, so there are problems.

Here are the ADO and Oracle major problems:

Ø        Oracle Bind parameters cannot be used.

Ø        Using ADO parameters in the select statement gives us a read-only recordset that forces us to do INSERT, UPDATE and DELETE in the command object, making programming more cumbersome.

Ø        Even though we’ve been promised otherwise that in Oracle 8 and up there are no more problems with In and Out parameters for Stored Procedures, this is not exactly the case. Also too many systems are still at level 7.x.

Ø       Cursor variables cannot be retrieved at all.

0040 has its own problems

Ø        0040 is pure Oracle. If you switch to say SQL Server you have to do a switch to ADO as well. The switch itself is so painful that the 0040 – ADO conversion is dwarfed by it anyway.

Ø        We miss the wonderful GetRows method of ADO. We may however mimic it in data classes.

Ø        If we do not use VB (and in future may be even with VB) we’ll miss the ability to do asynchronous programs. 0040, for the time being, lacks events. (we may however program around it in the COM)

Ø        0040 is slower (even though not very noticeably). Because 0040 is running in process (that is inside the same process space as your VB program) it is important to use early binding. The difference in performance will be astounding.

Hardly anybody talks about 0040. It is a hidden treasure. I hope that in the future you’ll consider it. Much more is written about it in my upcoming book - VB and Oracle Programmers Reference by Wrox Press.


 

Recent Jobs

Software Specialist, Linux - Finlan
Linux Core Technical Project Manage
Graphics designer at Tanzania. Expe
Integration Specialist Needed - Wor
Virtualization Server Infrastructur

View all Jobs (Add yours)
View all CV (Add yours)






    Email TopXML  

Front Page Daily Stuff TopXML Forum XML blogs XML Newsgroups BizTalk Biztalk Utilities Biztalk Utilities Tutorial B2B SAP XML Microsoft .NET Dotnet System XML Soapformatter SQLXML XMLserializer XQuery PHP PHP SimpleXML PHP XML Dom PHP XML RPC PHP XSLT Java Java Java XML Xalan Microsoft ASP ASP Schemas XML SQL Server XML XMLDom XSL XSL Tutorial XSLT Stylesheets General Javascript CSS XHTML WAP