Active Server Pages Frequently Asked Questions

    ActiveX Data Objects (ADO) General Questions

    Questions

    Connection Properties
    Time-out properties
    Parameter Values with Stored Procedures
    Time-outs
    Return Values in Stored Procedures
    Referencing DSNs
    AbsolutePosition
    Cursor Choices
    CacheSize Default
    Features of my Data Provider
    Connections
    Forward-Only Recordsets and Caching
    Working with Cursors Tips
    ADO and the OLE DB SDK
    Advanced OLE DB Provider Information
    Parameters
    RecordCount
    Using Input & Output Parameters
    Spaces in Table or Query Name
    Using GetChunk
    File DSN's

    Coding Examples
    Using Stored Procedures
    Using Input / Output Parameters

    Connection Properties


    QUESTION: How do I use ODBC options like TRACE, TRANSLATE, or any other driver or manufacturer specific options in ADO?
    ANSWER: The Connection.Properties collection contains provider-specific properties. When using the ODBC provider for OLE DB, the collection does not include tracing ODBC calls or controlling character set translation. To set the default values for these, use the ODBC administrator or the system registry as directed.
    Tip: For the specific properties that appear in the Connection.Properties collection when using the ODBC provider for OLE DB, check the ADO Web page at: http://www.microsoft.com/ado/

    Time-out properties

    QUESTION: I have tried setting both the Server.ScriptTimeout and the Connection.ConnectionTimeout properties to really high numbers (600 seconds), but the script is still timing after a minute or so. I can run the query from the SQL object manager and it finishes in about three minutes. When the user runs the report, he or she knows that the query may take several minutes and this is acceptable. I just need to get the Web page to be able to wait that long. Any ideas on how to troubleshoot?
    ANSWER: You need to set the Command.CommandTimeout property here instead of the Connection.ConnectionTimeout. The difference between these properties is that with the CommandTimeout, you are indicating how long to wait for the Command (your query) to execute, while with the Connection.ConnectionTimeout you are indicating how long to wait for the Connection to open.

    Parameter Values with Stored Procedures

    When executing a stored procedure, to use the defaulting parameter values, you should set the Command Parameter Value to EMPTY in the Visual Basic for Applications or Visual Basic Script environment. In the Java Script environment, Null should be used as an equivalent to EMPTY. For example:

    ' The following lines use MyValue1
    MyCommand.Parameters(0).Value = "MyValue1"
    MyCommand.Execute
    ' The subsequent lines use the default value
    MyCommand.Parameters(0).Value = EMPTY
    MyCommand.Execute
    ' The next lines indicate to use the provided value, MyValue2
    MyCommand.Parameters(0).Value = "MyValue2"
    MyCommand.Execute

    Time-outs

    QUESTION: What's the difference between a Connection CommandTimeout and a Command CommandTimeout?

    ANSWER: CommandTimeout on a Connection applies to the Connection.Execute & Recordset.Open where the Source property is not a Command object. If the Source of the Recordset.Open call is a genuine Command object, then it uses the CommandTimeout on the Command object instead of the Connection. Similarly, the Command.Execute uses the Command Object's property value.

    Return Values in Stored Procedures

    QUESTION: Does ADO (aka the Database Component in Active Server Pages) support Return Value parameters?
    ANSWER: Yes. In the following example, there is a Stored Procedure on SQL Server, a DSN called Pubs setup on the client machine to get to the pubs database on the SQL Server. There is a stored procedure called MyRetValSP, which has a Return Value (as in: create procedure outparam(@out int out) as Exec @out=MyRetValSP).


    Dim cmd As New Command
    cmd.ActiveConnection = "dsn=pubs;uid=sa;pwd=;database=master;"

    cmd.CommandText = "{ ? = call MyRetValSP}"
    cmd(0).Direction = adParamReturnValue

    cmd.Execute
    Debug.Print cmd(0)

    Note that this example is making an extra trip to the server, as the collection lookup (the line where cmd(0).Direction is called) causes an implicit refresh and thus forces an automatic parameter description. You could avoid this refresh by creating and appending your own parameter, with the Direction property set in the CreateParameter call.

    Referencing DSNs

    QUESTION: I can't seem to connect using ODBC File DSN. What do I need to do to make it work?
    ANSWER: You may not be providing a fully qualified path. To work without a fully qualified path, you need to locate the file in the working ODBC directory or to locate it in "Program files\Common files\Odbc\Data sources." Please see the Microsoft Office or ODBC 3.0 documentation for further information.

    AbsolutePosition

    QUESTION : I'm using my own OLE DB Provider, and when I set AbsolutePosition to 1, I get the 2nd row. Why don't I get the first row?
    ANSWER: For most cases, you won't run into this, but if you are using an OLE DB provider that supports IRowsetLocate, AbsolutePosition is 0 based instead of 1 based. You can check your provider using Recordset.Supports.

    Cursor Choices

    QUESTION : What is the cost or overhead of using a keyset or dynamic cursor, as opposed to a static or dynamic cursor? Why would I not always create dynamic cursors?
    ANSWER: There is no single cursor type you should always use. Your choice of cursor type would depend on the functionality you want like updatability, cursor membership, visibility and scrollability. Opening a keyset cursor may take time for building the key information if you have a lot of rows in the table whereas opening a dynamic cursor is much faster. You can however configure your data provider (such as SQL Server) to populate the key information asynchronously. Dynamic cursors don't support bookmarks. If you need bookmark support, go for a keyset or static cursor. Please refer to the documentation of ADO for further suggestions.

    CacheSize Default

    QUESTION: The online documentation says that the Cache size "Default is 1 for forward-only cursors, 10 for all other types.", but it defaults to 1.
    ANSWER: There is an error in the online documentation. It defaults to 1 for all cursor types.

    Features of my Data Provider

    QUESTION: I'm using ADO with the ODBC Driver and Access95 and am trying to do simple queries using the date/time fields in my database. What is the proper syntax for comparing date/time fields using ADO?
    ANSWER: ADO passes the command text you provide on to the provider, so it's up to you to make sure the provider you're calling supports the syntax. The following example, calls an Access 95 Northwind database and it assumes you have an ODBC DSN setup as "MyNorthWind".
    … Dim rs As New Recordset
    rs.Open "select * from employees where hiredate = #10/17/93#", "dsn=MyNorthWind;uid=sa;pwd=;"

    ' making sure that we got the right thing back
    While Not rs.EOF
    Debug.Print rs("hiredate")
    rs.MoveNext
    Wend

    Connections

    QUESTION: The following code creates a Command, opens a Connection and calls a Stored procedure. What else should I be aware of?
    <%
    Set cmd = Server.CreateObject("ADODB.Command")
    cmd.ActiveConnection = "dsn=sqlsvr;database=pubs;uid=sa;pwd=;"
    cmd.CommandText = "{call mysproc}"
    cmd.Execute
    %>

    ANSWER: A connection is opened underneath your Command object and it is released when the Command goes out of scope at the end of the page. If you want to release the Connection you can either set the Command object to reference Nothing as in:

    Set cmd = Nothing
    Or, you could close the connection by closing the Active connection as in:
    cmd.ActiveConnection.Close
    You should know that if you are using Connection Pooling, the REAL underlying connection may have been opened before you run this page of code, and it hangs around after you leave the page. See the Active Server Pages documentation for details.
    Other Tips With Connections:
    • Use a Connection variable, instead of a Connection string as the ActiveConnection for Commands. By using a Connection variable, you're calling an existing connection. If you use a string you are creating a new connection for the command.
    • Clean up after yourself. Close Active Connections when you are done with them. You should also explicitly Close a connection when you are done with the connection and it is no longer needed. A connection is closed when it goes out of scope (when it's apparent you no longer need it). You can proactively call Close when you know that you no longer need a connection to free up resources before it goes out of scope.
    • (SQL Server specific) With a forward-only, read only-cursors (aka Firehose cursors) against SQL Server, you cannot start a transaction on that connection. This is because the connection is dealing with the cursor and needs to complete what it's doing (get to the end of the cursor) before continuing.
    • (SQL Server specific) It is a good idea to separate your Firehose cursor code from your Command Execution code. For example, you could get in situation where the same SQL pages are used, such as a query "Select * from TableX" and an update to TableX. Without setting your CommandTimeout you could hang.

    Forward-Only Recordsets and Caching

    QUESTION: The Recordset.Move documentation describes using the Cache as a way to retrieve records in a Forward-Only cursor in a backwards fashion by using the Cache. Is there anything I should look out for in doing so?
    ANSWER: You should use the appropriate cursor for your situation, meaning, if you need to move backwards don't use a Forward-Only cursor type. But, if you must use this capability to handle limited backwards mobility with a Forward-Only cursor, you should avoid moving to the EOF as that releases your cached group. Instead, you should use Move to get to the specific record you want.

    Working with Cursors Tips

    The default for opening a recordset is forward-only, read-only. Some providers have a "firehose" mode, meaning they efficiently retrieve data by keeping a connection open to retrieve data. When working with such providers, the connection could be blocked from being used in a transaction. For example, the following examples demonstrate scenarios that result in errors.

    Example 1: The problem is that the Command object's ActiveConnection is being set to a Connection that is forward-only and in "firehose" mode. This is the same Connection involved in the batch mode. The error from the provider appears only in the Err object, and it returns as unspecified. For example, with the msdasql provider, you get "Unspecified error".

    MyConnection.Open "MyDSN", "MyLogin", "MyPwd"
    MyConnection.BeginTrans
    MyRecordset.Open MySelectStatement, MyConnection
    Set MyCommand.ActiveConnection = MyConnection

    Example 2: The problem is that the Connection is forward-only and in "firehose" mode, so you cannot put it into transaction mode. The error returned in Errors from the provider indicates that it is dealing with the firehose mode and cannot work in transaction mode. For example, with the msdasql provider against Microsoft SQL Server, you get the error "Can not start transaction while in firehose mode."

    MyConnection.Open "MyDSN", "MyLogin", "MyPwd"
    MyRecordset.Open MySelectStatement, MyConnection
    MyConnection.BeginTrans

    Example 3: The problem is that the Connection is in a forward-only and "firehose" mode, so it cannot be involved in a batch mode. The error returned in Errors from the provider indicates that the transaction could not be started. For example, with the msdasql provider against Microsoft SQL Server, you get the error "Cannot start transaction because more than one hdbc is in use."

    MyConnection.Open "MyDSN", "MyLogin", "MyPwd"
    MyRecordset.Open MySelectStatement, MyConnection
    Set MyCommand.ActiveConnection = MyConnection
    MyConnection.BeginTrans

    ADO and the OLE DB SDK

    QUESTION: I installed ADO previously when I installed the OLE DB SDK 1.0 last August. The ADO that is delivered in Active Server Pages is different and my previous ADO code does not run. Why?
    ANSWER: ADO was shipped as a preview technology in the OLE DB SDK. There will be a 1.1 upgrade to the OLE DB SDK in the December/January timeframe. This upgrade will include the final release version of ADO 1.0 (the same DLLs that ship with Active Server Pages), an enhanced ODBC Provider (the same DLLs that ship with Active Server Pages), and several other components. The ADO preview samples and documentation will also be updated to correspond with the release version of ADO. In addition, the 1.1 SDK will include a list of distinctions since the ADO Preview, and some new samples.

    Advanced OLE DB Provider Information

    The default OLE DB provider for Active Server Pages is the msdasql provider that allows you to get to ODBC data sources.

    There is a Supports property on the Recordset object that can be tested to determine what features/capabilities are supported by the OLE DB provider.

    Msdasql does not provide support for a feature known as IRowsetScroll, and thus allows for the AbsolutePosition property to be written and read. Reading this property gives -1, -2, or -3 but never an actual position in the rowset. Writing to the property works but may not be extremely efficient as it asks the provider to read data after skipping the AbsolutePosition rows from the start of the start bookmark.

    Parameters

    QUESTION: When I try to set the parameter value to a string greater than 255, I get "String data right truncation" error. What's going on?
    ANSWER: You need to set the Type to adLongVarChar to avoid this error when you execute. Here's an example that uses an SQL Server PUBS database (with a DSN setup as 'Pubs'):

    Dim cmd As Command
    Dim conn As New Connection
    Dim param As Parameter

    On Error GoTo HandleErr

    conn.Open "Pubs", "sa"

    Set cmd = New Command
    Set cmd.ActiveConnection = conn

    cmd.CommandText = "DROP PROC Bug26bSP"
    cmd.CommandType = adCmdText
    cmd.Execute

    cmd.CommandText = "Create Procedure Bug26bSP (@ADOInParam text) AS RETURN(1)"
    cmd.CommandType = adCmdText
    cmd.Execute

    cmd.CommandText = "Bug26bSP"
    cmd.CommandType = adCmdStoredProc
    cmd.Parameters.Refresh

    Debug.Print "Param 1 Type : "; cmd(1).Type
    Debug.Print "Param 1 Size : "; cmd(1).Size

    ' Executing generates an error "String data right truncation"
    ' unless you set the Field.Type to adLongVarChar
    'cmd(1).Type = adLongVarChar
    cmd(1).Value = String(256, "A")

    cmd.Execute

    Exit Sub

    HandleErr:
    Debug.Print "Err Num : "; Err.Number
    Debug.Print "Err Desc: "; Err.Description
    Resume Next

    RecordCount

    QUESTION: After I delete a record, the Record count still includes the deleted record. Why?
    ANSWER: If you were to refresh or requery the recordset would not include the deleted record and the RecordCount would be accurate. If you set your CacheSize to 1 (so that you are only caching one record at a time) the RecordCount accurately excludes deleted rows. You should avoid increasing the CacheSize with a keyset cursor in circumstances when you are expecting to be able to delete and use RecordCount.

    Using Input & Output Parameters

    QUESTION: I get a "bad parameter" error when I execute a Command that calls a Stored Procedure that uses an output parameter. What do I need to do to get this to work?
    ANSWER: ADO creates an Output parameter if you set the CommandText appropriately and call Refresh on the Parameters collection. If you run into a "bad Parameter" error it is possible that there is a problem with the allocation of size. Since a size was not provided, the provider tells ADO the potential size of the parameter. ADO then tries to accommodate the potential size, which for Image and Text data type on SQL Server can be around 2 gigabytes, which triggers the "bad parameter" admonishment. To avoid this problem, provide the Size before executing.

    Spaces in Table or Query name

    QUESTION: I get an error saying it couldn't find the input table or query when I try to reference my table "My Table" or my query "My Query". Why doesn't this work?


    Set DBConn = Server.CreateObject("ADODB.Connection")
    DBConn.ConnectionTimeout = Session("DBConn_ConnectionTimeout")
    DBConn.CommandTimeout = Session("DBConn_CommandTimeout")
    DBConn.Open Session("DBConn_ConnectionString"), Session("DBConn_RuntimeUserName"), Session("DBConn_RuntimePassword")
    Set cmdTemp = Server.CreateObject("ADODB.Command")
    Set DataCommand1 = Server.CreateObject("ADODB.Recordset")
    cmdTemp.CommandText = "My Query2"
    cmdTemp.CommandType = adCmdTable
    Set cmdTemp.ActiveConnection = DBConn
    DataCommand1.Open cmdTemp, , 0, 1

    ANSWER: You are setting the CommandType to adCmdTable for a query name that contains a space. You would run into the same problem if your table name also had a space in it.

    To work around this problem, you could build your own SQL statement ("select * from [My Query2]"), or you might try not specifying the CommandType.

    Using GetChunk

    QUESTION: What is the best way to use GetChunk to retrieve large text fields?
    Here is the code I am working with currently. (I have verified that the record is retrieved):

    Set ADODBConnection = Server.CreateObject("ADODB.Connection")
    ADODBConnection.Open "Data Source=xxx", "xxx", "xxx"
    sSQLQuery = "SELECT MyStuff, MyStuff_txt FROM MyStuff_webview WHERE MyStuff = " & Request.QueryString("MyStuff")
    Set RSSummary = ADODBConnection.Execute(sSQLQuery)
    txtMyStuff = RSSummary.Fields("MyStuff_txt").GetChunk(1000)

    ANSWER: You should try to avoid using GetChunk on a Forward-Only cursor (which is what happens when you call Execute and pass only your SQL query statement). If you must use chunks, then open the recordset as a Keyset or Static cursor. If you need to get the "complete field" then you should use Field.Value instead of GetChunk.

    File DSNs

    QUESTION: How do I use file DSNs with SQL Server? The following gives me an error:

    Set oConnection = CreateObject("ADODB.Connection")
    oConnection.Open "file name=xyz.dsn"

    ANSWER: You should use the "filedsn" tag instead of "file name" and try including a path.

    CODING EXAMPLES

    In the following examples, it is assumed that you have an SQL Pubs database setup with a DSN named "pubs".
    • Cursors
    • Using Stored Procedures
    • Using input/output parameters

    Cursors
    Sub SimpleCursor()

    Set con = CreateObject("adodb.connection")
    con.Open "pubs", "sa", ""
    ' creates a forward-only, read-only cursor
    Set rs = con.Execute("select * from authors")

    End Sub

    Sub MoreFunctionalCursor()

    Set con = CreateObject("adodb.connection")
    con.Open "pubs", "sa", ""
    Set rs = CreateObject("adodb.recordset")
    ' asks for a keyset cursor (with bookmark support) and optimistic concurrency
    rs.Open "select * from authors", con, adOpenKeyset, adLockOptimistic

    End Sub

    Using Stored Procedures
    ADO supports accessing a stored proc with text parameters. Here's an example:

    Sub textparam()

    Dim con As New Connection, cmd As New Command, rs As Recordset

    con.Open "pubs", "sa", ""

    On Error Resume Next
    con.Execute "drop table texttable"
    con.Execute "drop procedure textproc"
    On Error GoTo 0
    con.Execute "create table texttable(text text)"
    con.Execute "create procedure textproc @text text as insert texttable values(@text)"

    Set cmd.ActiveConnection = con
    cmd.CommandText = "textproc"
    cmd.CommandType = adCmdStoredProc
    cmd.Parameters.Append cmd.CreateParameter("foo", adLongVarChar, adParamInput, 5000)

    cmd(0) = String(1000, "A")
    cmd.Execute

    cmd(0) = String(2000, "B")
    cmd.Execute

    Set rs = con.Execute("select text from texttable")
    While Not rs.EOF
    v = rs(0)
    Debug.Print Len(v), v
    rs.MoveNext
    Wend

    End Sub

    Using Input/Output Parameters
    The following example demonstrates using input and output parameters & assumes that you have a DSN named MyPubs that gets you to an SQL Server Pubs database.


    Dim cmd As New Command, con As New Connection
    con.Open "MyPubs", "sa", ""

    On Error Resume Next
    con.Execute "drop procedure MySPOut"
    On Error GoTo 0
    con.Execute "create procedure MySPOut( @in char(200), @out char(200) out ) as select @out = @in"

    Set cmd.ActiveConnection = con
    cmd.CommandText = "{call MySPOut(?, ?)}"

    ' specify parameter info
    cmd.Parameters.Append cmd.CreateParameter("in", adChar, , 200, "foo")
    cmd.Parameters.Append cmd.CreateParameter("out", adChar, adParamOutput, 200)

    cmd.Execute


Last Reviewed: Tuesday, February 13, 2001