[Maher Associates, Inc. Logo] [Actuarial & Computer Consulting]

MS SQL Server Issues

Buy SQL Developers Edition

Visual Basic and Access

Differences in coding directly to SQL compared to Access

ODBC vs Jet Coding Differences

There are differences in syntax and features between operations in each type of workspace. While this is not an exhaustive list, it is a start in understanding how to convert your Jet code to ODBCDirect. Most of these apply to creating passthrough queries in a Jet workspace as well.

  1. OpenRecordset syntax is different as you must handle lock options when opening the recordset.
  2. rs.Lockedits is not supported in ODBCDirect
  3. Any dbSQLPassThrough queries must be converted to dbExecDirect
  4. FindFirst is not supported in ODBCDirect
  5. Bookmarks and lastmodified are not supported in ODBCDirect
  6. You cannot put a ";" at the end of a query statement
  7. In Jet you use # to delimit a date. In ODBCDirect you use ' (#12/31/97# vs '12/31/97')
  8. In Jet you do Select Top N to return a specific number of records. For ODBCDirect, you must add SET ROWCOUNT N before your query string and SET ROWCOUNT 0 at the end of the query string.
  9. You cannot use [] around field names or table names in ODBCDirect. They shouldn't be necessary since SQL tables and fields cannot have spaces
  10. When you reference a bit field in a Where clause, you cannot simply use the field name. You must specify BitField=0 or BitField<>0

Datasource Issues

Basic VB/Access Approaches to Using SQL Data

ODBC Direct Example - Open Recordset for Editing

Dim wrkSpace as Database
Dim dbData as Database
Dim rs as Recordset

Set wrkSpace = CreateWorkspace("Endorse", "admin", "", dbUseODBC)
Workspaces.Append wrkSpace

sqlDB = utlReadIniFile(App.Path & "\ppacgi.ini", "sql", "Database")
sqlDSN = utlReadIniFile(App.Path & "\ppacgi.ini", "sql", "DSN")
Set dbData = wrkSpace.OpenDatabase(sqlDB, dbDriverNoPrompt, False, "ODBC;DATABASE=" & sqlDB & ";UID=sa;PWD=;DSN=" & sqlDSN)
cSQL = "Select * from UWMaster where Policy = " & CStr(chgset!Policy)
Set rs = dbData.OpenRecordset(cSQL, dbOpenDynamic, dbExecDirect, dbOptimistic)

ODBC Direct Example - Calling a Stored Procedure to open a recordset

Dim ws as workspace
Dim rs as Recordset
Dim conn as connection

Set ws = CreateWorkspace("SQL", "admin", "", dbUseODBC)
Workspaces.Append ws
sqlDSN = utlReadIniFile(App.Path & "\premd.ini", "paths", "SQLDSN")
sqldb = utlReadIniFile(App.Path & "\premd.ini", "paths", "SQLDATABASE")
Set conn = ws.OpenConnection("Connection1", dbDriverNoPrompt, False, "ODBC;DATABASE=" & sqldb & ";UID=sa;PWD=;DSN=" & sqlDSN)

conn.QueryTimeout = 0 'make sure process doesn't time out
Set rs = conn.OpenRecordset("MakePremiumDetail", dbOpenSnapshot, dbExecDirect)

ODBC Direct Example - Calling a Stored Procedure using Execute

Assuming you have a connection variable, conn, in a JET workspace, you can call a stored procedure using Execute to perform an action - as opposed to getting back records.

cSQL = "Update Master SET CancelFlag = 'Y'"
conn.Execute cSQL, dbExecDirect

Adding Records in SQL Tables with Identity Columns

In an ODBC Direct workspace, you can open a recordset for a table with an identity (called Autonumber or Counter in Access) column and add a new record. Since you cannot use lastmodified to return to the correct record, you have to move to the record by some other means. In this example, the cSQL statement will not return any records.

Set rs = db.OpenRecordset(cSQL, dbOpenDynamic, dbExecDirect, dbOptimistic)

rs.AddNew
rs!UserName = cUsername
rs!StartDate = Date
rs!UnverifiedFlag = bUnverify
rs!Inuse = cUsername
rs.Update
rs.MoveFirst
BNum = rs!BatchNumber
getBatchNumber = BNum

In a JET workspace, you must use the dbSeeChanges option. Unlike ODBC Direct, you can use lastmodified to locate the record you added. You also need the dbSeeChanges if doing an Execute to perform an Update query.

ODBC Direct Example using QueryDefs

With a connection or database variable, you can define a querydef to call a stored procedure. With this approach, you can have output parameters in the stored procedure and a way to return them to VB. One way to use this approach is to have the stored procedure return the error code, if any.

Set qd = conn.CreateQueryDef("")
qd.SQL = "{Call MakeDecCancelsActive(?, ?)}" 'the ? holds the place of the parameter
qd.ODBCTimeout = 0 'make sure query doesn't time out
qd.Parameters(0).Direction = dbParamInput
qd.Parameters(1).Direction = dbParamOutput
qd.Parameters(0) = iPolicy
qd.Execute dbRunAsync 'or you can set a recordset from the querydef: set rs = db.OpenRecordset
Do While qd.StillExecuting
    'do stuff while query is executing
    DoEvents
Loop
p = qd.Parameters(1) 'to access the returned parameter

Other SQL Examples using ODBC workspace

Example Illustrating differences between ODBCDirect and Jet with Transactions

With Jet, if you add a record to a table and then query from that table, you will timeout. This can be done, however, in ODBCDirect. With the following code, set bUseODBC to determine how you want the code to run. This example also shows coding differences. Note that either approach will work without the transaction.

Dim d As Date, bUseODBC As Boolean
d = #12/31/97#
Randomize
bUseODBC = True

If bUseODBC Then
	Set ws = CreateWorkspace("ODBCWorkspace", "admin", "", dbUseODBC)
Workspaces.Append ws
	Set db = ws.OpenDatabase("PPADATA", dbDriverNoPrompt, False, cConnection)
Else
	Set ws = CreateWorkspace("", "admin", "", dbUseJet)
	Set db = ws.OpenDatabase("", dbDriverNoPrompt, False, _
		"ODBC;DATABASE=ppadata;UID=sa;PWD=;DSN=PPADATAsql")
End If

ws.BeginTrans
If bUseODBC Then
	Set rs = db.OpenRecordset("Select * from CtrlPrint where Policy=0", _
		dbOpenDynamic, dbExecDirect, dbOptimistic)
Else
	Set rs = db.OpenRecordset("Select * from CtrlPrint where Policy=0", dbOpenDynaset)
End If
rs.AddNew
rs!Policy = 100000
rs!Expiration = d
rs!Revision = 0
rs!ItemNumber = CInt(Rnd * 100)
rs!PrintJob = "TEST"
rs.Update
rs.Close

If bUseODBC Then
	Set rs = db.OpenRecordset("Select * from CtrlPrint where Policy = 100000", _
		dbOpenDynamic, dbExecDirect, dbOptimistic)
Else
	db.QueryTimeout = 5 'set so won't take so long when timing out
	'this will time out regardless of what Policy is used
	'if add dbSQLPassThrough option the query will not timeout. 
	'However, you can't edit the recordset below
	Set rs = db.OpenRecordset("Select * from CtrlPrint where Policy = 100000", dbOpenDynaset)
End If
While Not rs.EOF
	rs.Edit
	rs.Update
	Debug.Print rs!PrintJob
	rs.MoveNext
Wend
rs.Close

ws.CommitTrans
ws.Close

Note that this represents my current understanding of programming in VB using Microsoft SQL. Use this advice with caution. I do not assume any responsibility for problems you encounter using these ideas.

[Mailbox Icon]For information, contact Christopher P. Maher: chris@maherassociates.com

Copyright © 1996 - 2004 Maher Associates, Inc.
Site Last modified: July 18, 2004-AZ