2015-08-18 2 views
1

Моя проблема заключается в том, что с каждой итерацией цикла обновления я теряю около 100 тыс. Памяти, поэтому, в конце концов, я получаю ошибку ресурса после нескольких тысяч итераций.Microsoft Access 2010 Memory Leak DAO recordset и RUNSQL

Вопрос в том, почему я теряю память?

Ниже приведен фрагмент кода, который является обновлением цикла.

Критерии извлекаются из локальной базы данных методом dao.recordset. - rs1

Сравнение происходит из целевой базы данных, где будет выполнено обновление, метод dao.recordset. - rs2 является целью чтения, чтобы проверить, нужно ли мне делать обновление.

Обновление представляет собой запрос Docmd.Runsql в связанную таблицу общих совпадений. И да, я знаю, что могу использовать .edit и .update, но в этом случае другие странные вещи случаются для другого поста. :)

Access 2010 в Sharepoint 2010

Dim db As DAO.Database 
Dim rs1 As DAO.Recordset 
Dim rs2 As DAO.Recordset 

Set db = CurrentDb 
Set rs1 = db.OpenRecordset("datefix") 

Do While Not rs1.EOF 
    Set rs2 = db.OpenRecordset("select `Required delivery` from xyzzy where `SO Line` = '" & rs1.Fields(0).Value & "'") 
    If rs1.Fields(1).Value = rs2.Fields("Required delivery") Then 
    Else 
     DoCmd.RunSQL "update ProblemTracking set `Required delivery` = '" & rs1.Fields(1).Value & "', `1st GI Dat` = '" & rs1.Fields(2).Value & "' where `SO Line` = '" & rs1.Fields(0).Value & "'" 
    End If 
    rs2.Close 
    Set rs2 = Nothing 

    rs1.MoveNext 
Loop 
+0

Да, я наблюдаю, как размер памяти MSACCESS.EXE растет с каждой итерацией. Закрытие позже. Похоже, что память растет на 100 кбайт. – user3666385

+0

Попробуйте использовать currentdb.Execute. Документ завернут в транзакцию, и это может быть причиной отказа памяти. –

ответ

0

Рассмотрим преобразовании VBA в один наборов записей хранится запрос действий. Вы видите в SQL, JOIN считается явным соединением, а WHERE считается неявным соединением. Оптимизаторы выполняют эти два эквивалентно. А в запросах обновления могут использоваться утверждения объединения. Кроме того, хранимые запросы в отличие от запросов VBA анализируются, оптимизируются и кэшируются базой данных с оптимальным планом выполнения, хранящимся внутри компании.

Если я прочитал ваш код правильно, у вас есть три таблицы: datefix, xyzzy и ProblemTracking все присоединились SO Line (и все, что соответствующий столбец в dateFix в вашем примере используют номера полей, а не имена). В принципе, вам необходимо обновить поля [Required delivery] и в ProblemTracking всякий раз, когда соответствующий второй столбец dateFix не равен [Required delivery] в xyzzy.

Таким образом, следует сохранить ниже Update Query как его собственный объект и запустить его в VBA с DoCmd.OpenQuery:

UPDATE (ProblemTracking 
INNER JOIN datefix ON ProblemTracking.`SO Line` = datefix.`FirstColumn`) 
INNER JOIN xyzzy ON xyzzy.`SO Line` = datefix.`FirstColumn` 
    SET `Required delivery` = datefix.`SecondColumn`, `1st GI Dat` = datefix.`ThirdColumn` 
WHERE datefix.SecondColumn <> xyzzy.`Required delivery` 

Теперь, если выше не является updatedatable query, используйте DLookUp():

UPDATE ProblemTracking 
INNER JOIN datefix 
ON ProblemTracking.`SO Line` = datefix.`FirstColumn` 
WHERE datefix.SecondColumn <> 
     DLookUp("[Required delivery]", "xyzzy", "[SO Line]='" & datefix.FirstColumn & "'") 

Но если вы настаиваете на использовании наборов записей VBA, все еще рассматриваете возможность объединения всех трех таблиц в запросе SELECT, где вы используете только один набор записей.

Dim db As DAO.Database 
Dim rs As DAO.Recordset 

Set db = CurrentDb 

' PULLING ONLY NEEDED COLUMNS IN JOIN OF THREE TABLES 
strSQL = "SELECT datefix.`FirstColumn`, datefix.`SecondColumn`, datefix.`ThirdColumn`" _ 
      & " FROM (ProblemTracking" _ 
      & " INNER JOIN datefix ON ProblemTracking.`SO Line` = datefix.`FirstColumn`)" _ 
      & " INNER JOIN xyzzy ON xyzzy.`SO Line` = datefix.`FirstColumn`" _ 
      & " WHERE datefix.SecondColumn <> xyzzy.`Required delivery`;" 

Set rs = db.OpenRecordset(strSQL) 

rs.MoveLast 
rs.MoveFirst 

Do While Not rs.EOF 
    DoCmd.RunSQL "UPDATE ProblemTracking 
        SET `Required delivery` = '" & rs.Fields(1).Value & "', 
         `1st GI Dat` = '" & rs.Fields(2).Value & "' 
        WHERE `SO Line` = '" & rs.Fields(0).Value & "'" 
    rs.MoveNext 
Loop 

rs.Close 
Set rs = Nothing 
+0

Предоставлено много способов обмануть этого кота, и вы предоставили 3 хороших и интересных варианта, вопрос остается, ПОЧЕМУ есть утечка памяти в моем примере ??? :) – user3666385

+0

Это может быть связано с различными причинами (размер базы данных, размер таблицы, пользователи, сборщик мусора VBA, оперативная память, дисковое пространство и т. Д.). Вместо того, чтобы анализировать и размышлять, я предоставляю несколько более эффективных стратегий, особенно потому, что вы создаете/уничтожаете набор записей с каждой итерацией цикла. Дайте мне знать, если это помогает в утечке памяти. – Parfait