Question

I am working on a system that has been in use since the 90's. Written in VB6, it was originally setup to utilize an Access Database and the JET driver.

Now, since we have clients running up against the 2GB file size limit on Access DBs, we are looking into converting everything over to mySQL.

Unfortunately, everything in the system that was written prior to about 5 years ago is using this type of logic:

Dim rst As New ADODB.Recordset
rst.ActiveConnection = cnn
rst.Open "table"
rst.Index = "index"
rst.Seek Array("field1", "field2"), adSeekFirstEQ
rst!field1 = "something new"
rst.Update

The newer code is using SQL commands like SELECT, UPDATE, etc. So, what we're hoping to do is to phase in the new mySQL DBs for our clients - get them the DB setup but using all the old code.

The problem is that I can't use Index when using the SQL db... everything else seems to work fine except for that. I get the error: #3251: Current provider does not support the necessary interface for Index functionality.

Is there something I'm missing? Is there another way to so a Seek when using SQL so that I can sort by my Index? Or will I have to go in and change the entire system and remove all the Seek logic - which is used THOUSANDS of times? This is particularly an issue for all of our Reports where we might have a Table with an Index where Col 1 is sorted ASC, Col 2 is sorted DESC, Col 3 is ASC again and I need to find the first 5 records where Col 1 = X. How else would you do it?

Was it helpful?

Solution

Since, as you posted, the DB doesn't support Seek or Index, you're kind of out of luck as far as that is concerned.

However, if you really must use seek /index I'd suggest importing the result of the SQL query into a local .mdb file and then using that to make the recordset work like the rest of the code expects.
This is slightly evil from a performance point of view, and honestly it may be better to replace all the seeks and index calls in the long run anyways, but at least it'll save you time coding.

For creating the local db you can do:

Function dimdbs(Temptable as String)
Dim tdfNew As TableDef
Dim prpLoop As Property
Dim strDbfullpath As String
Dim dbsn As Database
Dim idx As Index
Dim autofld As Field
'PARAMETERS: DBFULLPATH: FileName/Path of database to create

strDbfullpath = VBA.Environ$("TMP") & "\mydb.mdb"
If Dir(strDbfullpath) <> "" Then
           Set dbsn = DBEngine.Workspaces(0).OpenDatabase(strDbfullpath)
Else
    Set dbsn = DBEngine.CreateDatabase(strDbfullpath, dbLangGeneral)
End If

Set tdfNew = dbsn.CreateTableDef(Temptable)
With tdfNew
      ' Create fields and append them to the new TableDef
      ' object. This must be done before appending the
      ' TableDef object to the TableDefs collection of the
      ' database.
        Set autofld = .CreateField("autonum", dbLong)
        autofld.Attributes = dbAutoIncrField
        .Fields.Append autofld
        .Fields.Append .CreateField("foo", dbText, 3)
        .Fields.Append .CreateField("bar", dbLong)
        .Fields.Append .CreateField("foobar", dbText, 30)
        .Fields("foobar").AllowZeroLength = True
        Set idx = .CreateIndex("PrimaryKey")
        idx.Fields.Append .CreateField("autonum")
        idx.Unique = True
        idx.Primary = True
        .Indexes.Append idx

        Debug.Print "Properties of new TableDef object " & _
         "before appending to collection:"

      ' Enumerate Properties collection of new TableDef
      ' object.
      For Each prpLoop In .Properties
         On Error Resume Next
         If prpLoop <> "" Then Debug.Print "  " & _
           prpLoop.Name & " = " & prpLoop
         On Error GoTo 0
      Next prpLoop

      ' Append the new TableDef object to the Northwind
      ' database.
      If ObjectExists("Table", Temptable & "CompletedCourses", "Userdb") Then
        dbsn.Execute "Delete * FROM " & Temptable & "CompletedCourses"
      Else
      dbsn.TableDefs.Append tdfNew
      End If



      Debug.Print "Properties of new TableDef object " & _
         "after appending to collection:"

      ' Enumerate Properties collection of new TableDef
      ' object.
      For Each prpLoop In .Properties
         On Error Resume Next
         If prpLoop <> "" Then Debug.Print "  " & _
           prpLoop.Name & " = " & prpLoop
         On Error GoTo 0
      Next prpLoop

    End With
    Set idx = Nothing
    Set autofld = Nothing
End Function

to find and delete it later you can use the following:

Function DeleteAllTempTables(strTempString As String, Optional tmpdbname As String = "\mydb.mdb", Optional strpath As String = "%TMP%")
Dim dbs2 As Database
Dim t As dao.TableDef, I As Integer
Dim strDbfullpath
If strpath = "%TMP%" Then
    strpath = VBA.Environ$("TMP")
End If
strDbfullpath = strpath & tmpdbname
If Dir(strDbfullpath) <> "" Then
    Set dbs2 = DBEngine.Workspaces(0).OpenDatabase(strDbfullpath)
Else
    Exit Function
End If
        strTempString = strTempString & "*"
      For I = dbs2.TableDefs.Count - 1 To 0 Step -1
         Set t = dbs2.TableDefs(I)
         If t.Name Like strTempString Then
            dbs2.TableDefs.Delete t.Name
         End If
      Next I
dbs2.Close

End Function

To import from SQL to that DB you'll have to get the recordset and add each record in using a for loop (unless it's a fixed ODBC connection, i think you can import directly but I don't have example code)

Dim formrst As New ADODB.recordset
Set mysqlconn = New ADODB.Connection
Dim dbsRst As recordset
Dim dbs As Database
'opens the ADODB connection to my database
Call openConnect(mysqlconn)
'calls the above function to create the temp database
'Temptable is defined as a form-level variable so it can be unique to this form 
'and other forms/reports don't delete it
Call dimdbs(Temptable)
Me.RecordSource = "SELECT * FROM [" & Temptable & "] IN '" & VBA.Environ$("TMP") & "\mydb.mdb'"
Set dbs = DBEngine.Workspaces(0).OpenDatabase(VBA.Environ$("TMP") & "\mydb.mdb")
Set dbsRst = dbs.OpenRecordset(Temptable)

Set formrst.ActiveConnection = mysqlconn
Call Selectquery(formrst, strSQL & strwhere & SQLorderby, adLockReadOnly, adOpenForwardOnly)
With formrst
    Do Until .EOF
            dbsRst.AddNew
            dbsRst!foo = !foo
            dbsRst!bar = !bar
            dbsRst!foobar = !foobar
            dbsRst.Update
        .MoveNext
    Loop
    .Close
End With
dbsRst.Close
Set dbsRst = Nothing
dbs.Close
Set formrst = Nothing

You'll have to re-import the data on save or on form close at the end, but at least that will only need one SQL statement, or you can do it directly with the ODBC connection.

This is by far less than optimal but at least you can couch all this code inside one or two extra function calls and it won't disturb the original logic.

I have to give huge credit to Allen Browne, I pulled this code from all over the place but most my code probably comes from or has been inspired by his site (http://allenbrowne.com/)

OTHER TIPS

Who wants to use VB6? Nevertheless...

When you do not specify Provider, you can't use Index property. As far as i know only OleDb for MS Jet supports *Seek* method and *Index* property. Please read this:

Seek method - http://msdn.microsoft.com/en-us/library/windows/desktop/ms675109%28v=vs.85%29.aspx

Index property - http://msdn.microsoft.com/en-us/library/windows/desktop/ms675255%28v=vs.85%29.aspx

ConnectionString property - http://msdn.microsoft.com/en-us/library/windows/desktop/ms675810%28v=vs.85%29.aspx

Provider property - http://msdn.microsoft.com/en-us/library/windows/desktop/ms675096%28v=vs.85%29.aspx

For further information, please see: http://msdn.microsoft.com/en-us/library/windows/desktop/ms681510%28v=vs.85%29.aspx

[EDIT]
After your comments...
I would strongly recommend to download and install Visual Studio Express Edition and use VB.NET instead VB6. Than install ADO.NET MySQL Connector and re-write application, using the newest technology rather than torturing yourself with ADODB objects, etc.

Examples:
Connecting to MySQL databases using VB.NET
[/EDIT]

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top