2013-12-19 1 views
3

Я работаю над системой, которая использовалась с 90-х годов. Написанная в VB6, она была первоначально настроена на использование базы данных Access и драйвера JET.Использование ADODB.Recordset.Index при подключении к MySQL ODBC в VB6

Теперь, поскольку у нас есть клиенты, работающие против ограничения размера файла 2 ГБ на БД доступа, мы изучаем преобразование всего в mySQL.

К сожалению, все в системе, которая была написана до около 5 лет назад, используя этот тип логики: команды

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 

Новый код использует SQL как SELECT, UPDATE и т.д. Итак, то, что мы надеемся сделать, состоит в том, чтобы фазировать новые базы данных mySQL для наших клиентов - получить их настройку БД, но используя весь старый код.

Проблема в том, что я не могу использовать Index при использовании SQL db ... все остальное работает нормально, за исключением этого. Я получаю ошибку: #3251: Current provider does not support the necessary interface for Index functionality.

Есть что-то, что мне не хватает? Есть ли способ использовать Seek при использовании SQL, чтобы я мог сортировать по моему индексу? Или мне нужно будет войти и изменить всю систему и удалить всю логику Seek, которая используется ТЫСЯЧИ раз? Это особенно актуально для всех наших отчетов, где у нас может быть таблица с индексом, где Col 1 сортируется ASC, Col 2 сортируется DESC, Col 3 - это ASC снова, и мне нужно найти первые 5 записей, где Col 1 = X. Как еще вы это сделаете?

+0

Интересно, я никогда не видел этот метод использования Index/Seek с ADO! В большинстве случаев, которые я видел, открываются наборы записей, проверяя полный запрос SELECT с соответствующим предложением ORDER BY. Я собирался предположить, что вы могли бы создать связанные таблицы в Access, указывающие на новую базу данных MySQL, но беглый веб-поиск, по-видимому, подразумевает, что это не будет поддерживаться. –

+0

Да, весь новый код, который я написал, использует SELECT и ORDER BY, это просто, что весь старый код этого не делает, и потребуется много времени и работы, чтобы преобразовать весь старый код - который мы надеваем Прямо сейчас. – SeiferTim

+0

Да, но если вы хотите переместить данные в MySQL, я не уверен, что у вас есть большой выбор? Возможно, вы могли бы разделить базу данных Access на несколько файлов данных (http://stackoverflow.com/questions/11257326/how-to-increase-ms-access-2007-database-size)? Похоже, что ['Seek' можно заставить работать] (http://access.mvps.org/access/tables/tbl0006.htm) в этом сценарии. –

ответ

1

Поскольку, как вы писали, БД не поддерживает Seek или индекс, ты вроде не повезло, насколько это обеспокоен.

Однако, если вы действительно необходимы использования искать/индекс Я хотел бы предложить импортировать результат запроса SQL в локальный файл .mdb, а затем с помощью, чтобы сделать работу, как набор записей остальной частью коды надеется.
Это немного плохое с точки зрения производительности, и, честно говоря, в любом случае, возможно, лучше заменить все запросы на вызовы и индексы в долгосрочной перспективе, но, по крайней мере, это сэкономит вам время на кодирование.

Для создания локальной БД вы можете сделать:

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 

, чтобы найти и удалить его позже вы можете использовать следующее:

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 

Чтобы импортировать из SQL в этой БД вы будете иметь для получения набора записей и добавления каждой записи в цикл for (если это не фиксированное соединение ODBC, я думаю, что вы можете импортировать напрямую, но у меня нет кода примера)

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 

Вам нужно будет повторно импортировать данные по сохранению или по форме в конце, но по крайней мере вам потребуется только один оператор SQL, или вы можете сделать это напрямую с помощью ODBC-соединения.

Это намного менее оптимально, но, по крайней мере, вы можете убрать весь этот код внутри одного или двух дополнительных вызовов функций, и это не повредит исходной логике.

Я должен дать огромный кредит Allen Browne, я вытащил этот код со всего местом, но большинство моего кода, вероятно, происходит от или был вдохновлен его сайтом (http://allenbrowne.com/)

+0

Я не уверен, насколько практично это будет в реальном мире, но это именно тот ответ, который я искал! Благодаря! – SeiferTim

1

Кто хочет использовать VB6? Тем не менее ...

Если вы не указали Поставщика, вы не можете использовать свойство Index. Насколько я знаю только OleDb для MS Jet поддерживает * Ищет * метод и * Индекс * property. Пожалуйста, прочитайте это:

Seek метод - http://msdn.microsoft.com/en-us/library/windows/desktop/ms675109%28v=vs.85%29.aspx

Index свойство - http://msdn.microsoft.com/en-us/library/windows/desktop/ms675255%28v=vs.85%29.aspx

ConnectionString недвижимость - http://msdn.microsoft.com/en-us/library/windows/desktop/ms675810%28v=vs.85%29.aspx

Provider недвижимость - http://msdn.microsoft.com/en-us/library/windows/desktop/ms675096%28v=vs.85%29.aspx

Для получения дополнительной информации, пожалуйста, см: http://msdn.microsoft.com/en-us/library/windows/desktop/ms681510%28v=vs.85%29.aspx

[EDIT]
После ваших комментариев ...
Я настоятельно рекомендую к download and install Visual Studio Express Edition и использовать vb.net вместо VB6. Затем установите ADO.NET MySQL Connector и перезапишите приложение, используя новейшую технологию, а не пытаясь с помощью объектов ADODB и т. Д.

Примеры:
Connecting to MySQL databases using VB.NET
[/ EDIT]

+0

Итак, я думаю, что вы говорите, что нет возможности подключиться к базе данных mySQL и по-прежнему сохранять что-нибудь близкое к функциям «Index/Seek»? Если я подключаюсь к SQL, он должен использовать SQL-запросы ('SELECT',' UPDATE' и т. Д.)? – SeiferTim

+0

Не обязательно ... Я пытаюсь сказать, что вам нужно проверить это: ** Использовать метод _Supports (adSeek) _, чтобы определить, поддерживает ли базовый провайдер Seek и метод _Supports (adIndex) _, чтобы определить провайдер поддерживает индексы. ** –

+0

Я уже знаю, что они не поддерживают Seek и Index, но я говорю, что у меня около 20 000 мест в коде, которые в настоящее время используют эти методы, - и затем продолжайте, как если бы эти функции работал, и я пытаюсь понять, что я могу сделать, чтобы по крайней мере приблизиться к работе так же, чтобы я мог сделать минимальные изменения кода ... – SeiferTim