У меня есть большое приложение MS Access с большим количеством вычислений в коде VBA. Когда я запускаю его, он в конечном итоге вылетает из-за чрезмерного размера файла. Создается множество промежуточных таблиц и запросов, которые впоследствии удаляются, но Access не освобождает пространство. Я старательно закрыл все промежуточные наборы записей и установил все временные объекты в ничто, но ничего не помогает. Единственный способ запустить свой код - запустить его часть, остановить и восстановить / сжать файл, а затем перезапустить код.
Нет лучшего способа?
Спасибо

Я не MVP, но Google нашел их. Может, они вам помогут:
http://www.mvps.org/access/general/gen0041.htmhttp://forums.devarticles.com/microsoft-access-development-49/compact-database-via-vba-24958.html
К сожалению, у MS Access возникают проблемы, когда вы становитесь слишком большими - я думаю, что максимальный размер составляет 2 ГБ для доступа к базе данных.
Вы можете подумать о переходе на Sql Express, VistaDB и т. д.
Я не знаю ни одной последней версии Windows, в которой было бы ограничение на размер файла 2 ГБ. Это правда, что это не ограничение Доступ - это ограничение Jet, и оно жестко встроено в Jet.
Позднее добавление: некоторые файловые системы, такие как FAT32, имеют ограничение на размер файла 2 ГБ. Но никто больше не использует FAT32 в Windows - это исчезло со смертью семейства Win9x версий Windows.
С какими размерами вы имеете дело? Какой код ошибки при сбое? Я был бы удивлен, если бы это произошло просто потому, что файл стал «слишком большим», но я полагаю, что есть предел. Судя по вашему описанию всего временного, могут быть улучшения в дизайне, которые могут помочь.
Обновлено: Я ожидаю, что вы понимаете, что заменить базу данных чем-то еще нетривиально - даже если вы попытаетесь сохранить все, что есть в mdb, кроме таблиц. Определения запросов доступа уникальны, Access SQL нестандартен, и вам придется начинать заново.
Большинство приложений Access, которые я видел, имеют много возможностей для рефакторинга; и обычно это не так сложно, если: а) вы понимаете логику и бизнес-правила и б) хорошо разбираетесь в программировании в Access. Но это было бы более или менее верно для любых альтернатив. Если бы я был на вашем месте, и вам немного не хватило бы ни в одной области, возможно, вы могли бы получить некоторую помощь. Но сначала я бы попытался спасти приложение Access.
Также есть предложение от другого автора о перемещении таблиц в один или несколько прикрепленных MDB. В целом это надежная, хорошо зарекомендовавшая себя техника. Но сначала я должен понять, в чем настоящая причина проблемы.
Я не согласен с вами. Я переместил довольно большие базы данных MS Access в MS SQL без особых проблем (нет, это не тривиально); но подавляющее большинство определений запросов и т. д. работают без изменений (особенно если они связаны с таблицами SQL в базе данных Access). Вы не начинаете заново,
Вы должны иметь возможность запускать компактную функцию из кода VBA.
У меня был приведенный ниже фрагмент, который был добавлен в закладки давным-давно, когда я выполнял работу с доступом.
Public Sub CompactDB()
CommandBars("Menu Bar").Controls("Tools").Controls("Database utilities").Controls("Compact and repair database...").accDoDefaultAction
End Sub
Вы можете поместить это в свой код, чтобы обойти это.
ПРИМЕЧАНИЕ: вы также можете рассмотреть возможность перехода на более крупную систему БД, если у вас возникают проблемы с масштабированием такого типа.
Замечу, что инструмент «Сжатие и восстановление» иногда создает поврежденную базу данных (нечитаемую). Рекомендуется ВСЕГДА делать резервную копию своей базы данных перед запуском на ней инструмента. Мне кажется, что автоматический запуск из кода - очень рискованная операция.
Как бы это было реализовано, если у вас есть разделенная база данных и серверная часть растет?
Согласно http://office.microsoft.com/en-us/access/HP051868081033.aspx, Access 2003 и 2007 имеют ограничение в 2 ГБ. Однако легко переместить некоторые или все таблицы в отдельный файл .mdb, а затем связать их с этими таблицами. В любом случае рекомендуется иметь два файла: один для ваших данных, а другой для всех макросов, запросов и т. д. У вас даже может быть несколько файлов, если ваш файл таблицы приближается к пределу в 2 ГБ.
Я бы перенес данные в MS SQL (постоянные данные и промежуточные таблицы); и вы можете пока оставить часть кода в MS Access.
Это решает две большие проблемы:
Оба эти фактора означают, что больше не нужно сжимать / восстанавливать базу данных; вы можете получить бесплатную версию (Express Edition) MS SQL, и это не так уж и сложно.
Если вы не хотите переключаться на SQL Express или аналогичный, вы можете копать следующие идеи:
Положение дел в отношении размеров файлов Jet для меня бесконечно проблематично.
В настоящее время я наблюдаю за частью моего собственного кода VBA из базы данных Access A, поскольку он выполняет серию полей с одной записью обновления с использованием ADO для таблицы в базе данных Access B (через ссылку на обновляемый запрос в базе данных A). Единственное поле - это СИМВОЛ (8). После каждых 4 обновлений база данных B увеличивается примерно на 8 Кбайт. Этому нет оправдания. Увеличение размера файла сильно снижает производительность; при каждом росте файла обновление происходит медленно, примерно от одной записи в секунду (в таблице, содержащей около 30-40 тысяч записей, использующих поиск по одной записи SQL без каких-либо индексов) до одного за 5-10 секунд. Я признаю, что я сжал / восстановил базу данных B перед запуском этого кода обновления; возможно, если бы я этого не сделал, спектакль не был бы таким плохим. Если бы целевое поле для обновления было, скажем, типа Memo, я бы этого ожидал. Но выполнять обновление поля CHAR () и получить такой результат просто неразумно.
Большая часть из вышеперечисленного (без особой критики в отношении какого-либо одного задуманного решения) кажутся допустимыми решениями для приложений, которые используют относительно постоянную структуру бизнес-приложений (постоянно обращаются к одним и тем же целевым базам данных). У меня не так. . . Я не могу изменить целевую базу данных (база данных B), поскольку она создается и используется инструментом поставщика, который мы используем для экспорта и импорта данных из их приложения.
Я понимаю и благодарю вышеупомянутых авторов за решения проблем пользователей. Однако я не могу допустить, чтобы дизайн / реализация программного обеспечения бедные мешали пользователям, использующим продукт, поскольку пользователи ожидают, что он будет работать.
Для меня допущение обновления одной записи за раз - это красный флаг. Вы уверены, что это невозможно сделать с помощью пакетного ОБНОВЛЕНИЯ SQL? Во-вторых, здесь нет ничего удивительного. Jet / ACE хранит записи в полях переменной длины. Изменение данных в поле нефиксированной длины приведет к изменению длины записи и потребует перезаписи ее на другой странице данных. Все это сделано по дизайну и на самом деле не сильно отличается от любого механизма базы данных, который когда-либо существовал (кроме тех, что были в те дни, когда дисковое пространство было гораздо более ограниченным, чем это было, когда Jet был разработан в начале 90-х).
Я столкнулся с аналогичной проблемой, когда моя база данных раздувалась при импорте необработанных данных. Вместо обычного разделения базы данных и сжатия серверной части я решил использовать объект базы данных (DAO) для создания временной базы данных, импорта данных, запроса / изменения данных в этой временной базе данных, перетаскивания их в исходную базу данных через SQL и затем удалите его. Код YBase показан ниже:
Sub tempAccessDatabaseImport()
Dim mySQL As String
Dim tempDBPath As String
Dim myWrk As DAO.Workspace
Dim tempDB As DAO.Database
Dim myObject
'Define temp access database path
tempPathArr = Split(Application.CurrentProject.Path, "\")
For i = LBound(tempPathArr) To UBound(tempPathArr)
tempDBPath = tempDBPath + tempPathArr(i) + "\"
Next i
tempDBPath = tempDBPath + "tempDB.accdb"
'Delete temp access database if exists
Set myObject = CreateObject("Scripting.FileSystemObject")
If myObject.FileExists(tempDBPath) Then
myObject.deleteFile (tempDBPath)
End If
'Open default workspace
Set myWrk = DBEngine.Workspaces(0)
'DAO Create database
Set tempDB = myWrk.CreateDatabase(tempDBPath, dbLangGeneral)
'DAO - Import temp xlsx into temp Access table
mySQL = "SELECT * INTO tempTable FROM (SELECT vXLSX.*FROM [Excel 12.0;HDR=YES;DATABASE = " & RAWDATAPATH & "].[" & WORKSHEETNAME & "$] As vXLSX)"
'DAO Execute SQL
Debug.Print mySQL
Debug.Print
tempDB.Execute mySQL, dbSeeChanges
'Do Something Else
'Close DAO Database object
tempDB.Close
Set tempDB = Nothing
myWrk.Close
Set myWrk = Nothing
'Delete temp access database if exists
If myObject.FileExists(tempDBPath) Then
'myObject.deleteFile (tempDBPath)
End If
End Sub
Ограничение в 2 ГБ имеет смысл, но, скорее всего, это не ограничение доступа, а ограничение ОС. То есть, поскольку доступ хранит свои данные в одном файле, ограничение на размер файла в 2 ГБ в ОС может стать точкой отказа.