Appendix L ActiveX Data Objects

The purpose of this appendix is to provide a brief overview of ActiveX Data Objects (ADO), which is the standard component provided by Microsoft for accessing databases and other structured data sources. Since ADO is a provided as a library of COM objects, you can use ADO in your VBScript programs to write to and read from databases. Our purpose here is not to discuss all of the details and powerful features of ADO. Rather, since ADO is so often used in combination with VBScript, our goal is to provide a brief overview and reference.

ADO is too large a subject to cover thoroughly in one appendix. If you are making significant use of ADO in your scripts, you may want to purchase a book dedicated to ADO. Given the brevity of this overview, we also assume that you are familiar with basic relational database concepts such as tables, columns , queries, stored procedures, and so on.

This guide to ADO covers ADO 2.8, which is the latest version of ADO available at press time. Please note that, since VBScript is a pre-.NET technology, we will not be discussing ADO.NET, which is the latest version of ADO. ADO.NET is intended for use by .NET languages such as C# and VB.NET. It is not natively compatible with VBScript. If you want to ensure that you have the latest version of ADO, you can download the latest release of Microsoft Data Access Components (MDAC) from msdn.microsoft.com/data .

Our discussion will include the following ADO objects:

  • Connection -Used to connect to a data source and manage transactions.
  • Command -Used to execute commands such as queries and stored procedures against a data source.
  • Parameters and Parameter - Parameter objects are stored in the Command object's Parameters collection. Together, Parameter and Parameters are used to specifyparameters for a stored procedure being called through a Command object.
  • Recordset -Used to store a series of structured data-usually data returned from a query or stored procedure-represented as a series of rows and columns. You can also use the Recordset object to manually construct a data set that you wish to submit to a database.
  • Error -If one or more errors occur while using any of the ADO objects, the Connection object's Errors collection will contain one or more Error objects. An Error object has information about an error such as the number, description, and source.

Please note that we are not covering the Record or Stream objects as these are more advanced than our basic ADO overview. Also, we do not have separate sections for the Fields and Field objects, but the basic usage of these are covered in the section on the Recordset object.

The example code in this appendix is based on the Northwind sample database that ships with Microsoft Access. The downloadable script files are designed for running under the Windows Script Host (see Chapter 12), but the code is easily transferable to other hosts . Our discussion will focus on using ADO for relational database access, since that it by far the most common use for ADO, but keep in mind that since ADO is part of Microsoft's 'Universal Database' strategy, it can be used to access other structured data formats such as spreadsheets, e-mail systems, text files, and so on.

Finally, please note that certain advanced or seldom used properties and methods may be excluded for some objects.

The Connection Object

The Connection object is almost always required in order to do anything interesting with the other ADO objects. The Connection object represents the primary access point to a data source. If you want to read from or write to a data source, you need to use the Connection object to establish a connection with that data source. The following example script ( ADO_CONNECTION.VBS ) illustrates the basic technique for opening a connection.



Option Explicit




Const adStateOpen = 1




Dim cnNorthwind




Dim strStatus




Set cnNorthwind = CreateObject(ADODB.Connection)




cnNorthwind.ConnectionString = _




Provider=Microsoft.Jet.OLEDB.4.0; & _




User ID=Admin;Password=;Data Source= & _




C:  Program Files Microsoft Office Office Samples & _




Northwind.mdb




cnNorthwind.Open




If cnNorthwind.State = adStateOpen Then




MsgBox Connection is open.




Else




MsgBox Connection is not open.




End If




cnNorthwind.Close




Set cnNorthwind = Nothing


After instantiating the Connection object, this code sets the ConnectionString property. The connection string is how you tell the Connection object what kind of data source to connect to ( Provider= ), how to locate that data source ( Data Source= ), and security information for logging into the data source ( User , ID= and Password= ). To get this connection string to work on your machine, you may have to change the path to the Northwind.mdb file.

Unfortunately, there are many different ³provider ³ types for different data source types and many different versions of these providers. There are also different styles of connection strings that different providers may or may not support. Unfortunately, there is not enough space here to include information on the dozens of different providers and connection string formats. Please consult the documentation for the type of database you are using. There is also an excellent comprehensive connection string reference available online at http://www.able-consulting.com/ADO_ Conn.htm.

Going back to the script, after setting the connection string, we call the Open method, which tells the Connection object to attempt to connect to the data source. Finally, just to prove that our connection was successful, we check the State property to find out the status of the connection. Notice also that we call the Close method when we are done with the connection. It is always a good idea to close any database connections as soon as you are done with them.

The following two sections describe in detail the important Connection object properties and methods.

Connection Object Properties

Name Accepts/Returns Access Description

CommandTimeout

Long

Read/Write

Used to set or obtain the number of seconds a Connection object will wait when executing a command (see Execute method) before giving up; has no effect on the CommandTimeout property of the Command object.

ConnectionString

String

Read/Write

Used to set or obtain the connection details for a data source, including provider type, data source location, user name, and password.

ConnectionTimeout

Long

Read/Write

Used to set or obtain the number of seconds a Connection object will wait when connecting to a data source (see Open method) before giving up.

CursorLocation

Long ( CursorLocationEnum )

Read/Write

Used to set or obtain the location of the ³cursor ³ of any Recordset objects opened with a Connection object; a cursor can be ³client-side ³ or ³server-side.

³ Errors

Collection

Read Only

If an error occurs during usage of a Connection object, this collection will contain one or more Error objects, which have properties exposing error number, description, source, and so on.

State

Long ( ObjectStateEnum )

Read Only

Returns information about the status of a connection to a data source. Most often, the status is either ³open ³ or ³closed ³; other statuses apply when using asynchronous methods on ADO objects using the connection.

Connection Object Methods

Name Arguments Returns Description

BeginTrans

None

Long

Used to begin a transaction at the data source; must be followed, eventually, by a call to either CommitTrans or RollbackTrans; the Long return value (seldom used) indicates the ³nesting level ³ of the new transaction

CommitTrans

None

N/A

Used to ³commit ³ a transaction that was started with a call to BeginTrans

RollbackTrans

None

N/A

Used to abort a transaction that was started with a call to BeginTrans

Cancel

None

N/A

Used to abort a method call (such as Connection.Execute or Recordset.Open ) that was executed asynchronously

Close

None

N/A

Used to close an open connection; important to call this when done using a Connection object, before setting it to Nothing

Execute

CommandText - String value containing an SQL query, stored procedure call, or URL to execute at the data source

RecordsAffected -Optional Long in/out argument that will contain the number of records returned by the data source

Options -Optional Long value indicating the type of command in the CommandText argument; can be any combination of values from CommandTypeEnum and ExecuteOptionEnum

Recordset object

To execute a command on adata source, you can use either the Execute method of the Connection object or the Command object; use a Command object when you need to pass parameters to a stored procedure; otherwise Connection.Execute is a convenient shortcut; for an SQL query, use adCmdText ( 1 ) in the Options argument; for a stored procedure, use adCmdStoredProc ( 4 )

Open

ConnectionString -Optional String value that can be used in place of, or to override, the ConnectionString property

UserID -Optional String value that can be used in place of specifying a user ID in the connection string

Password -Optional String value that can be used in place of specifying a password in the connection string

Options -Optional Long ( ConnectOptionEnum ) value; default value of adConnectUnspecified causes normal, synchronous connection; adAsyncConnect will cause asynchronous connection

N/A

Opens a connection object; traditionally, most programmers set the ConnectionString property before calling Open instead of using the arguments of the Open method


The Command Object

The Command object is an optional alternative to using the Execute and Open methods of the Connection object. Some programmers prefer the explicitness of using a Command object insteadof Connection.Execute and Connection.Open . Other programmers prefer the brevity of using the Connection object. The choice is up to you. Note, however, that if you are calling a stored procedure that uses parameters, you pretty much have to use the Command object instead of Connection. Execute or Connection.Open .

The following script ( ADO_COMMAND.VBS ) demonstrates the basic technique of using an SQL query to open a Recordset object from the Northwind database's Suppliers table. This script example borrows from the Connection object example in the previous section and will be continued in the Recordset object section, later.



Option Explicit




Const adCmdText = 1




Const adStateOpen = 1




Dim cnNorthwind




Dim cmdQuery




Dim rsSuppliers




Set cnNorthwind = CreateObject(ADODB.Connection)




cnNorthwind.ConnectionString = _




Provider=Microsoft.Jet.OLEDB.4.0; & _




User ID=Admin;Password=;Data Source= & _




C:  Program Files Microsoft Office Office Samples & _




Northwind.mdb




cnNorthwind.Open




Set cmdQuery = CreateObject(ADODB.Command)




With cmdQuery




Set .ActiveConnection = cnNorthwind




.CommandText = SELECT [SupplierID], [CompanyName] & _




FROM Suppliers & _




WHERE [Country] = 'Australia'




.CommandType = adCmdText




Set rsSuppliers = .Execute




End With




If rsSuppliers.State = adStateOpen Then




MsgBox Recordset opened successfully.




rsSuppliers.Close




End If




Set rsSuppliers = Nothing




Set cmdQuery = Nothing




cnNorthwind.Close




Set cnNorthwind = Nothing


Notice that once we have an open Connection object, we instantiate a Command object and set the ActiveConnection property of the Command to the Connection object. This gives the Command object its link to the data source. Next we set the CommandText property to an SQL query and set the CommandType to 1 , which is the value for the adCmdText enumerated constant (see ADO Enumerated Constants at the end of this appendix). Then we use the Execute method to run the query and return a Recordset object.

The Execute method may or may not return a Recordset depending on the type of command sent through CommandText . For example, an SQL UPDATE statement would not return a Recordset . In that case, you would just call the Execute method as a procedure instead of as a function.

Another common use of the Command object is calling a stored procedure (which may or may not return a Recordset ). In this case, most programmers use the Parameters collection to specify any parameters accepted by the stored procedure. The Parameter object section later includes an example of this syntax. (You can also pass parameters to a stored procedure in two other ways: one, as part of the CommandText or CommandStream property; and two, using the Parameters argument of the Execute method (which is not the same as the Parameters collection). Keep in mind that these alternative methods only support input-only parameters.

The following two sections describe in detail the important Command object properties and methods.

Command Object Properties

Name Accepts/Returns Access Description

ActiveConnection

Connection object (in a Variant )

Read/Write

Used to set or obtain a reference to a Connection object used by the Command; all ADO objects must go through a Connection object to get to the data source; this is usually the first property you would set after instantiating a Command object

CommandStream

Stream objec t

Read/Write

A mutually exclusive alternative to the CommandText property; whereas CommandText accepts/returns a String value and CommandStream accepts/returns a Stream object

CommandText

String

Read/Write

Used to set or obtain the string representing the ³command ³ that you wish the Command object to execute; can be an SQL query, stored procedure call, or URL; you should also set the CommandType property to the type value corresponding to the type of command

CommandTimeout

Long

Read/Write

Used to set or obtain the number of seconds a Command object will wait before giving up on a call to the Execute method

CommandType

Long ( CommandTypeEnum )

Read/Write

Must be set to match the type of command value placed into the CommandText or CommandStream property; use 1 ( adCmdText ) for SQL queries and 4 ( adCmdStoredProc ) for stored procedure calls

NamedParameters

Boolean

Read/Write

If the Command object is using the Parameters collection to pass parameters to a stored procedure, this property controls how those parameters are interpreted; True means that the parameters will be matched up by Parameter.Name with the parameter names defined in the stored procedure; False (the default) means that Parameter.Name is ignored and the parameters will be sent to the stored procedure in the order in which they are added to the Parameters collection

Parameters

Collection of Parameter objects

Read/Write

Holds a collection of Parameter objects; used when calling stored procedures that accept parameters; initially the collection is empty; Parameter objects must be added manually or can be auto- populated using the Parameters.Refresh method

Prepared

Boolean

Read/Write

Used to set or obtain whether the Execute method should tell the data source to cache a compiled version of the command, which can increase performance when repeatedly executing the same command

Command Object Methods

Name Arguments Returns Description

Cancel

None

N/A

If the Execute method was called asynchronously, a call to this method will abort the pending or in-progress command

CreateParameter

Name -Optional String value representing the parameter name Type -Optional Long value ( DataTypeEnum ) representing the data type of the parameter Direction -Optional Long value ( ParameterDirectionEnum ) indicating whether the parameter is input, output, or both Size -Optional Long value indicating the maximum parameter value length in bytes or characters Value -Optional Variant representing the value for the parameter (must correspond to the Type argument)

Parameter object

When calling a stored procedure and manually creating Parameter objects to add to the Parameters collection, use this method to create a new Parameter object; note that this method returns only a Parameter object-it does not add it to the Parameters collection; you can either use the arguments to initialize the Parameter object or omitthe arguments and manually set the properties on the returned Parameter object; if you use the arguments, the returned Parameter object will already have its properties set

Execute

RecordsAffected -Optional Long in/out argument that ADO will use to return the number of records affected by the command Parameters -Optional Variant array of parameters to pass to a stored procedure; does not support in/out parameters Options -Optional Long value indicating the type of command in the CommandText argument; can be any combination of values from CommandTypeEnum and ExecuteOptionEnum

Either returns a Recordset object, a Stream object, or Nothing , depending on the command sent to the data source

When you have prepared a Command object with properties such as CommandText , CommandType , and the Parameters collection, the Execute method will actually issue the command to the data source; depending on the content of the command, the data source may or may not return data, which influences the return type of the Execute method


The Parameters and Parameter Objects

The Parameter object is used in conjunction with the Command object and its Parameters collection. ³Parameter ³ in this context refers to parameters/arguments expected by a stored procedure that is being called with a Command object. There are actually a few ways to pass parameters to a stored procedure.

  • Embedding the parameters in the text of CommandText or CommandStream
  • Passing them in a Variant array to the Execute method's Parameters argument
  • Explicitly creating Parameter objects and adding them to the Command object's Parameters collection

Only the third technique actually involves the use of the Parameter object. Using the third technique has two advantages: one, the code is more explicit and a little more readable; and two, it supports in/out parameters, which the other two methods do not. On the downside, using the third method is a little slower since you have to instantiate ( potentially ) several Parameter objects for a single call to a stored procedure.

Using Parameter objects for passing parameters to a stored procedure involves these steps:

  1. Create a new Parameter object using Command.CreateParameter (using the arguments of the CreateParameter method to set the properties of the Parameter object)
  2. Adding the Parameter object to the Parameters collection using the Parameters.Append method
  3. Repeating the first two steps for as many times as the stored procedure's parameter list requires

All this must be done before calling the Execute method and, ideally , after setting the CommandText or CommandStream property of the Command object. Also, many programmers prefer to expedite the process by performing the first and second steps simultaneously . The following code snippet illustrates this technique ( please note that this code is not included in the downloadable code for this chapter since we are using Access for our examples and Access does not support stored procedures).



Const adCmdStoredProc = 4




Const adVarChar = 200




Const adParamInput = 1




Set cmdStoredProc = CreateObject(ADODB.Command)




With cmdStoredProc




Set .ActiveConnection = cnConnection




.CommandText = GetSuppliersByCountry




.CommandType = adCmdStoredProc




.Parameters.Append .CreateParameter(strCountry, _




adVarChar, adParamInput, 15, Australia)




Set rsSuppliers = .Execute




End With


The benefit of the shortcut used here is that you do not have to explicitly declare or instantiate any Parameter objects. The CreateParameter method returns a Parameter object that is immediately passed to the Parameters.Append method.

Another technique is to call the Command.Parameters.Refresh method after setting the stored procedure ame in CommandText or

CommandStream . The Refresh method will retrieve the parameter list from the data source and automatically populate the Parameters collection. Then you can loop back through the Parameters collection to set all of the Value properties. However, while this is a cool technique, it is usually avoided because of the extra round trip to the database.

The following two sections describe in detail the important Parameter object properties and methods.

Parameter Object Properties

Name Accepts/Returns Access Description

Direction

Long ( ParameterDirectionEnum )

Read/Write

Used to set or obtain the ³direction ³ for a stored procedure parameter; parameters can be input only ( adParamInput ), output only ( adParamOutput ), both input and output ( adParamInputOutput ), or return values ( adParamReturn )

Name

String

Read/Write before appended to Parameters , Read Only after appended

Depending on the value of Command.NamedParameters , the Name of a Parameter object may or may not be used in the execution of the stored procedure; if NamedParameters is True , Parameter.Name must match exactly the name of one of the stored procedure's parameters

NumericScale

Byte

Read/Write

Used to set or obtain the number of decimal places to which numeric parameter values are resolved

Precision

Byte

Read/Write

Used to set or obtain the precision for numeric parameters

Size

Long

Read/Write

Used to set or obtain the maximum size, in characters or bytes (depending on the Type ), for a parameter

Type

Long ( DataTypeEnum )

Read/Write

Used to set or obtain the data type of a parameter

Value

Variant

Read/Write

Used to set or obtain the value of a parameter; for output or input/output parameters, the value will be set by the stored procedure

Parameter Object Methods

Name Arguments Returns Description

AppendChunk

Data - Variant value to be appended to the Value property of the Parameter

N/A

In situations in which you are sending large amounts of text or binary data in a Parameter object, use the AppendChunk method to gradually build up the Value property rather than setting the Value property directly;for example, if you have 10,000 bytes of data you might call AppendChunk 10 times in a loop, appending 1000 bytes each time; can only be used when Type is adFldLong

Parameters Object Properties

Name Accepts/Returns Access Description

Count

Long

Read Only

Used to obtain the number of Parameter objects in the Parameters collection

Item

Parameter

Read Only

Used to obtain a reference to a certain Parameter object based on its index in the Parameters collection

Parameters Object Methods

Name Arguments Returns Description

Append

Parameter -A Parameter object that has already been initialized with Name , Type , Value , and so on

N/A

Used to add a new Parameter object to the Parameters collection; the Parameter object should have been created with Command.Create Parameter; its Type and Name properties must be set, but the Value can optionally be set or changed after appending

Delete

Index -The numeric collection index of the Parameter object you wish to remove from the Parameters collection

N/A

Used to remove a Parameter object from the Parameters collection

Refresh

None

N/A

If the ( Command.CommandText ) or CommandStream property has already been set with the name of a stored procedure, the Parameters.Refresh method will make a trip to the database to obtain the parameter list for the stored procedure and automatically populate the Parameters collection, after which you can loop through the collection to set the Value properties, if necessary


The Recordset Object

In general, setting aside the Stream object for a moment (see later), the Recordset is where a programmer can work with actual data. The typical scenario for the use of the Recordset object is that a programmer creates Connection and Command objects in order to execute a query or stored procedure in a database. The query or stored procedure returns a set of data, formatted as rows and columns , which is stored in a Recordset object. Then the programmer can use the Recordset object to read, update, add, or delete the data.

The Recordset object is also quite versatile beyond this typical scenario. It has a long list of properties and methods , and we could go on explaining all the cool things you can do with a Recordset . For example, you can programmatically create a Recordset object from scratch, create fields for it, and fill it up with data-all without using a data source at all. You can also save a Recordset to disk and re-create it later without having to connected to the original source of the Recordset . Recordset objects can even be nested inside of other Recordset objects. However, our focus here will be on the primary properties and methods used to work with Recordset objects that are returned by queries and stored procedures.

We will look at two example scripts: one that opens a Recordset from a query and loops through the data one time; and another that opens a Recordset , changes some of the data it contains, and updates the database with the changes. The following example script ( ADO _ RECORDSET_READ.VBS) illustrates the open and read technique.



Option Explicit




Const adCmdText = 1




Const adStateOpen = 1




Const adOpenForwardOnly = 0




Const adUseClient = 3




Const adLockReadOnly = 1




Dim cnNorthwind




Dim cmdQuery




Dim rsSuppliers




Dim strMsg




Set cnNorthwind = CreateObject(ADODB.Connection)




cnNorthwind.ConnectionString = Provider=Microsoft.Jet.OLEDB.4.0; & _




User ID=Admin;Password=;Data Source= & _




C:  Program Files Microsoft Office Office Samples & _




Northwind.mdb




cnNorthwind.Open




Set cmdQuery = CreateObject(ADODB.Command)




With cmdQuery




Set .ActiveConnection = cnNorthwind




.CommandText = SELECT [SupplierID], [CompanyName] & _




FROM Suppliers & _




WHERE [Country] = 'Australia'




.CommandType = adCmdText




End With




Set rsSuppliers = CreateObject(ADODB.Recordset)




Set rsSuppliers.Source = cmdQuery




rsSuppliers.CursorType = adOpenForwardOnly




rsSuppliers.CursorLocation = adUseClient




rsSuppliers.LockType = adLockReadOnly




rsSuppliers.Open




If rsSuppliers.State = adStateOpen Then




Do While Not rsSuppliers.EOF




strMsg = strMsg & rsSuppliers.Fields(SupplierID).Name




strMsg = strMsg & : & vbTab




strMsg = strMsg & rsSuppliers.Fields(SupplierID).Value




strMsg = strMsg & vbNewLine




strMsg = strMsg & rsSuppliers.Fields(CompanyName).Name




strMsg = strMsg & : & vbTab




strMsg = strMsg & rsSuppliers.Fields(CompanyName).Value




strMsg = strMsg & vbNewLine & vbNewLine




rsSuppliers.MoveNext




Loop




rsSuppliers.Close




MsgBox strMsg




Else




MsgBox Recordset not opened.




End If




Set rsSuppliers = Nothing




Set cmdQuery = Nothing




cnNorthwind.Close




Set cnNorthwind = Nothing


If you've been following along, you'll see that this is an extension of the example script from the previous Command object section. However, notice that we have changed the way we open the Recordset . Instead of using Command.Execute , we use CreateObject to instantiate an empty Recordset and then set the Command object to the Recordset.Source . A few lines later, when we call Recordset.Open , the Command object we put in the Source property (and its Connection object) is used to communicate with the database. This alternative method is necessary if you want to have control over some important properties of the Recordset before opening it.

In this example, we have set the CursorType property to adOpenForwardOnly , the CursorLocation to adUseClient ., and the LockType to adLockReadOnly . What this means is that we only intend to loop through this Recordset one time and that we want to do this as fast as possible while using the least amount of resources. Other cursor types, such as adOpenDynamic and adOpenKeyset , are more flexible in that they allow you to move back and forth between records and to loop through the Recordset more than one, but these cursor types incur more overhead and are therefore slower.

As far as CursorLocation , server-side cursors can enable certain Recordset features, such as the ability to receive dynamic updates to the data in the Recordset as it changes in the data source, but use more resources on the server. In this case we're not using those features, so we use a client-side cursor since it puts less of a tax on the database.

Finally, we set the LockType to adLockReadOnly since we do not intend to make any updates to the data. This is not strictly necessary since adLockReadOnly happens automatically when using adOpenForwardOnly , but it illustrates the point that CursorType , CursorLocation , and LockType have primary influence over what you can and can't do with a Recordset , how fast you'll be able to do it, and how much resource overhead you're incur.

When working with the Recordset object, it is important to have in mind how you plan to use the Recordset and then to set properties such as CursorType , CursorLocation , and LockType so that the Recordset will have the features you need while at the same time using the least amount of resources and offering the best performance. If you want to experiment to find out which capabilities are supported by which cursor types and locations (and this different depending on the ³Provider ³ specified in the connection string), you can use the Recordset.Supports method with CursorOptionEnum to find out if a feature you want (such as ³move previous ³ support or the ability to update the Recordset ) is supported by a certain cursor type and location.

After we open the Recordset , we use a Do loop to move through each of the records. One key to making this work is that we use the EOF property to make sure that we stop looping when we have reached the end (and that we don't start looping if the Recordset is empty). Another key to the loop is the call to Recordset.MoveNext right before the Loop statement. MoveNext moves the cursor to the next record. This call is essential or you will create an endless loop that reads the first record in the Recordset over and over again.

Inside the loop, we use the Fields collection, which returns a Field object based on the Name of the field, to read the data out of each record. The two important Field properties for us here are Name and Value . The Name is the same as the column name we used in the SQL query. The Value is the value that came back from the data source for that column on that row.

We turn now to our second example ( ADO_RECORDSET_WRITE.VBS ), which uses a Recordset object to update data.



Option Explicit




Const adCmdText = 1




Const adStateOpen = 1




Const adOpenKeyset = 1




Const adUseServer = 2




Const adLockOptimistic = 3




Dim cnNorthwind




Dim cmdQuery




Dim rsOrders




Dim datOrder




Set cnNorthwind = CreateObject(ADODB.Connection)




cnNorthwind.ConnectionString = Provider=Microsoft.Jet.OLEDB.4.0; & _




User ID=Admin;Password=;Data Source= & _




C:  Program Files Microsoft OfficesOfficesSamples  & _




Northwind.mdb




cnNorthwind.Open




Set cmdQuery = CreateObject(ADODB.Command)




With cmdQuery




Set .ActiveConnection = cnNorthwind




.CommandText = SELECT [OrderDate] & _




FROM Orders & _




WHERE [ShipCountry] = 'Italy'




.CommandType = adCmdText




End With




Set rsOrders = CreateObject(ADODB.Recordset)




Set rsOrders.Source = cmdQuery




rsOrders.CursorType = adOpenKeyset




rsOrders.CursorLocation = adUseServer




rsOrders.LockType = adLockOptimistic




rsOrders.Open




If rsOrders.State = adStateOpen Then




Do While Not rsOrders.EOF




datOrder = rsOrders(OrderDate)




If Not IsNull(datOrder) Then




'Add one second to the OrderDate




datOrder = DateAdd(s, 1, datOrder)




rsOrders(OrderDate) = datOrder




rsOrders.Update




End If




rsOrders.MoveNext




Loop




rsOrders.Close




MsgBox Finished updating recordset.




Else




MsgBox Recordset not opened.




End If




Set rsOrders = Nothing




Set cmdQuery = Nothing




cnNorthwind.Close




Set cnNorthwind = Nothing


First, notice that we have changed our query to return a list of order dates that are to be shipped to Italy. We did this because we want to be able to demonstrate an update operation without messing up your Northwind database if you decide to run this script on your machine. As we'll explain in a minute, and as you can see from reading the code, to keep the update as harmless as possible, we are adding one second to the OrderDate value.

Second, we have change the values we are using for the CursorType , CursorLocation , and LockType properties to a combination that will open an updateable Recordset . The adOpenKeyset cursor type will give us an updateable cursor that will detect any new records that are added while we have the Recordset open, but that does not use as many resources as adOpenDynamic . We changed the cursor location to adUseServer to support the adOpenKeyset cursor, which needs to run on the server in order to detect new records. Finally, we changed the lock type to adLockOptimistic to indicate that we want to update records but that we don't care if other users update the same records while we have the Recordset open. (If we did care, we would use adLockPessimistic .)

Inside of the loop, we retrieve the value of the OrderDate field, add one second to the date, and then write the new date value back to the field. We call the Update method to save to the database the change to the current record. Notice that we have altered the syntax we use to access the Recordset.Fields collection. This new syntax is a shorthand that takes advantage of the fact that the Fields property is the default property of the Recordset object and that the Value property is the default property of the Field object. Typing rsOrders.Fields(³OrderDate ³) is equivalent to just typing rsOrders(³OrderDate ³)

The following two sections describe in detail the important Recordset object properties and methods.

Recordset Object Properties

Name Accepts/Returns Access Description

BOF and EOF

Boolean

Read Only

Indicates whether the cursor is at the beginning of the Recordset or at the end; if the cursor is one position before the first record, BOF will be True; if one after the last record, EOF will be True; if directly on one of the records, both BOF and EOF will be False

CursorLocation

Long(CursorLocationEnum)

Read/Write before open; Read Only after open

As explained in the ³Overview ³ section above, CursorLocation is one of the essential properties for controlling cursor behavior and feature support; value can be either adUseClient or adUseServer

CursorType

Long (CursorTypeEnum)

Read/Write before open; Read Only after open

As explained in the previous section Overview , CursorType is one of the essential properties for controlling cursor behavior and feature support; different cursor types support different features; set the CursorType based on the features you need

Fields

Fields collection holding Field objects

Read Only

A Recordset is a matrix of columns and rows; the Fields property exposes the collection of columns, represented as Field objects; when reading a Recordset returned by a data source, you do not add or remove Field objects from the collection, but this can be done when working with a Recordset that is not associated with a data source

LockType

Long (LockTypeEnum)

Read/Write before open; Read Only after open

As explained in the previous section Overview , CursorType is one of the essential properties for controlling cursor behavior and feature support; if you do not need to update the data in the Recordset , use adLockReadOnly; for updates use either adLockOptimistic or adLockPessimistic , depending whether you need to protect against other processes changing data at the same time

RecordCount

Long

Read Only

Returns the number of records in the Recordset; will return -1 if the CursorType and CursorLocation do not support this feature; count may not be reliable if the cursor does not support ³approximate positioning ³ or ³bookmarks ³(see Supports method); you must use the exactly correct combination of CursorType and CursorLocation in order to depend on this property based on the underlying provider

Source

String or Command object

Read/Write before open; Read Only after open

If you wish to set properties such as CursorType and CursorLocation before opening the Recordset , create a Command object and set it into this property; you can also put an SQL query or stored procedure call string in this property if you also set the ActiveConnection property to a Connection object, but using a Command object that already has a Connection is more explicit

State

Long (ObjectStateEnum)

Read Only

Indicates the status of the Recordset; for example, adStateOpen or adStateClosed

Recordset Object Methods

Name Arguments Returns Description

AddNew

FieldList -Optional String or array of names or ordinal positions that must correspond to the fields in the Recordset. Fields collection Values -Optional String or array of values for the fields; elements must line up with the FieldList

N/A

If you are working with an updateable Recordset , use this to add a new record; you can either pass the fields and values as arguments to this method or omit the arguments and then set the value of each field as separate calls

Close

None

N/A

Closes an open Recordset; it's a good idea to always close a Recordset when you're done with it; will return an error if the Recordset is not open, so check the State property before calling Close

Delete

AffectRecords -Optional Long ( AffectEnum ) value indicating which records to include in the delete operation

N/A

Use this method to delete records from an updateable Recordset; most often, you would call this method while the cursor is positioned on the record you wish to delete-in which case you can omit the AffectRecords argument since the default is adAffectCurrent

MoveFirst MoveLast MoveNext MovePrevious

None

N/A

These four methods are used to move the cursor from its current position to another position; MoveNext is most often used since normally you start at the beginning of the Recordset and move through it one row at a time; if the CursorType and CursorLocation settings support it, you can use MoveFirst and MovePrevious to move the cursor backwards

Open

Source -Optional Variant that can contain a Command object, SQL string, or stored procedure call string; can be omitted if Source property is set ActiveConnection -Optional Variant that can contain an open Connection object or a connection string; can be omitted if ActiveConnection property is set or if the Command object has an open connection

CursorType -Optional Long ( CursorTypeEnum ) indicating desired cursor type; can be omitted if CursorType property is set

LockType -Optional Long ( LockTypeEnum ) indicating desired locking behavior; can be omitted if LockType property is set

Options -Optional Long value indicating how to treat Source argument if other than a Command object; can be any combination of values from CommandTypeEnum and ExecuteOptionEnum

N/A

As demonstrated in the Overview section earlier, used to open a Recordset using a certain source with certain options; you can either set the properties you want first and call Open with the arguments omitted, or you can pass the arguments to Open , which will set the corresponding properties automatically

Supports

CursorOptions - Long ( CursorOptionEnum ) value indicating which feature/behavior you wish to test

Boolean

Since the various features and behaviors of a Recordset object may or may not be available depending on CursorType and CursorLocation , this method is helpful in determining whether a given operation is supported

Update

Fields -Optional Variant containing a single field name or an array of field names or ordinal positions that must correspond to the fields in the Recordset.Fields collection Values -Optional Variant containing a single value or an array of values; elements must line up with Fields

N/A

Call this method after performing any edits of Field.Value or after a call to AddNew and before moving the cursor; data will not be saved until Update is called


ADO Enumerated Constants

A note regarding enumerated constants: enumerated constants are not directly supported by VBScript. This is unfortunate since they are an easy way to keep your code readable. For example, instead of setting

Command.CommandType with the value of 1 , you can set it to the value of adCmdText , making it a lot easier to understand what's going on in your code. However, there are two workarounds that can help you achieve that same code readability.

First, if you are writing an ASP (Active Server Pages) application, you can add this line to each of your pages that are going to include ADO code.






This include file is provided by Microsoft and should already be installed on your machine. This include file contains constant declarations equivalent to the ADO enumerated constants so that you can use them in your code just as if VBScript supported enumerated constants.

Second, if you are using another host, such as the Windows Script Host, you can declare named constants of your own as you need. We have used this technique with the example Windows Script Host scripts included with this appendix. Manually declaring your constants is a little tedious , but worth the trouble. Besides, you have to only declare the few that you're going to need in any given script. Take a look at these two equivalent lines of code and decide which one is more readable.



.Parameters.Append .CreateParameter(strCountry, _




200, 4, 15, Germany)




.Parameters.Append .CreateParameter(strCountry, _




adVarChar, adParamInput, 15, Germany)


If you're not using ASP, all that's required to achieve the improved readability of the second line is to add these two lines to your script.



Const adVarChar = 200




Const adParamInput = 1


Here are the ADO enumerated constants referred to in this ADO object reference.

Name Values

AffectEnum

adAffectAll-3

 

adAffectAllChapters-4

 

adAffectCurrent-1

 

adAffectGroup-2

CommandTypeEnum

adCmdUnspecified-1

 

adCmdText-1

 

adCmdTable-2

 

adCmdStoredProc-4

 

adCmdUnknown-8 (Default)

 

adCmdFile-256

 

adCmdTableDirect-512

ConnectOptionEnum

adAsyncConnect-16

 

adConnectUnspecified-1

CursorLocationEnum

adUseClient -3

 

adUseNone-1 (obsolete-do not use)

 

adUseServer-2

CursorOptionEnum

adAddNew-16778240 adApproxPosition-16384

 

adBookmark-8192

 

adDelete-16779264adFind-524288

 

adHoldRecords-256 adIndex-1048576

 

adMovePrevious-512

 

adNotify-262144

 

adResync-131072

 

adSeek-2097152

 

adUpdate-16809984

 

adUpdateBatch-65536

CursorTypeEnum

adOpenDynamic-2

 

adOenForwardOnly-0

 

adOenKeyset-1

 

adOpenStatic-3

 

adOpenUnspecified-1

DataTypeEnum

adArray-8192

 

adBigInt-20

 

adBinary-128

 

adBoolean-11

 

adBSTR-8

 

adChapter-136

 

adChar-129

 

adCurrency-6

 

adDate-7adDBDate-133

 

adDBTime-134

 

adDBTimeStamp-135

 

adDecimal-14

 

adDouble-5

 

adEmpty-0

 

adError-10

 

adFileTime-64

 

adGUID-72

 

adInteger-3

 

adLongVarBinary-205

 

adLongVarChar-201

 

adLongVarWChar-203

 

adNumeric-131

 

adPropVariant-138

 

adSingle-4

 

adSmallInt-2

 

adTinyInt-16

 

adUnsignedBigInt-21

 

adUnsignedInt-19

 

adUnsignedSmallInt-18

 

adUnsignedTinyInt-17adUserDefined-132

 

adVarBinary-204adVarChar-200

 

adVarNumeric-139

 

adVarWChar-202

 

adWChar-130

ExecuteOtionEnum

adAsyncExecute-16

 

adAsyncFetch-32

 

adAsyncFetchNonBlocking-64

 

adExecuteNoRecords-128

 

adExecuteStream-1024

 

adOptionUnspecified-1

LockTypeEnum

adLockBatchOptimistic-4

 

adLockOptimistic-3

 

adLockPessimistic-2

 

adLockReadOnly-1

 

adLockUnspecified-1

   

ObjectStateEnum

adStateClosed-0

 

adStateOpen-1

 

adStateConnecting-2

 

adStateExecuting-4

 

adStateFetching-8

ParameterDirectionEnum

adParamInput-1

 

adParamInputOutput-3

 

adParamOutput-2

 

adParamReturnValue-4

 

adParamUnknown-0




VBScript Programmer's Reference
VBScript Programmers Reference
ISBN: 0470168080
EAN: 2147483647
Year: 2003
Pages: 242

Flylib.com © 2008-2020.
If you may any questions please contact us: flylib@qtcs.net