Благодаря н.м. Свойства проекта VisualGDB- Настройки Makefile -Дополнительные входные данные компоновщика: -ldl, и он разработан
Возможно сделать немного с VBA. Например, вот запуск при создании сценария для базы данных с локальными таблицами.
Dim db As Database
Dim tdf As TableDef
Dim fld As DAO.Field
Dim ndx As DAO.Index
Dim strSQL As String
Dim strFlds As String
Dim strCn As String
Dim fs, f
Set db = CurrentDb
Set fs = CreateObject("Scripting.FileSystemObject")
Set f = fs.CreateTextFile("C:\Docs\Schema.txt")
For Each tdf In db.TableDefs
If Left(tdf.Name, 4) <> "Msys" Then
strSQL = "strSQL=""CREATE TABLE [" & tdf.Name & "] ("
strFlds = ""
For Each fld In tdf.Fields
strFlds = strFlds & ",[" & fld.Name & "] "
Select Case fld.Type
Case dbText
'No look-up fields
strFlds = strFlds & "Text (" & fld.Size & ")"
Case dbLong
If (fld.Attributes And dbAutoIncrField) = 0& Then
strFlds = strFlds & "Long"
Else
strFlds = strFlds & "Counter"
End If
Case dbBoolean
strFlds = strFlds & "YesNo"
Case dbByte
strFlds = strFlds & "Byte"
Case dbInteger
strFlds = strFlds & "Integer"
Case dbCurrency
strFlds = strFlds & "Currency"
Case dbSingle
strFlds = strFlds & "Single"
Case dbDouble
strFlds = strFlds & "Double"
Case dbDate
strFlds = strFlds & "DateTime"
Case dbBinary
strFlds = strFlds & "Binary"
Case dbLongBinary
strFlds = strFlds & "OLE Object"
Case dbMemo
If (fld.Attributes And dbHyperlinkField) = 0& Then
strFlds = strFlds & "Memo"
Else
strFlds = strFlds & "Hyperlink"
End If
Case dbGUID
strFlds = strFlds & "GUID"
End Select
Next
strSQL = strSQL & Mid(strFlds, 2) & " )""" & vbCrLf & "Currentdb.Execute strSQL"
f.WriteLine vbCrLf & strSQL
'Indexes
For Each ndx In tdf.Indexes
If ndx.Unique Then
strSQL = "strSQL=""CREATE UNIQUE INDEX "
Else
strSQL = "strSQL=""CREATE INDEX "
End If
strSQL = strSQL & "[" & ndx.Name & "] ON [" & tdf.Name & "] ("
strFlds = ""
For Each fld In tdf.Fields
strFlds = ",[" & fld.Name & "]"
Next
strSQL = strSQL & Mid(strFlds, 2) & ") "
strCn = ""
If ndx.Primary Then
strCn = " PRIMARY"
End If
If ndx.Required Then
strCn = strCn & " DISALLOW NULL"
End If
If ndx.IgnoreNulls Then
strCn = strCn & " IGNORE NULL"
End If
If Trim(strCn) <> vbNullString Then
strSQL = strSQL & " WITH" & strCn & " "
End If
f.WriteLine vbCrLf & strSQL & """" & vbCrLf & "Currentdb.Execute strSQL"
Next
End If
Next
f.Close
Если Вы рады использовать что-то другое, чем чистый Доступ SQL, Вы могли бы сохранить набор объектов ADOX и использовать их для воссоздания структуры таблицы.
Пример (в Python, в настоящее время не воссоздает отношения и индексы, поскольку он не был необходим для проекта, я продолжал работать):
import os
import sys
import datetime
import comtypes.client as client
class Db:
def __init__(self, original_con_string = None, file_path = None,
new_con_string = None, localise_links = False):
self.original_con_string = original_con_string
self.file_path = file_path
self.new_con_string = new_con_string
self.localise_links = localise_links
def output_table_structures(self, verbosity = 0):
if os.path.exists(self.file_path):
if not os.path.isdir(self.file_path):
raise Exception("file_path must be a directory!")
else:
os.mkdir(self.file_path)
cat = client.CreateObject("ADOX.Catalog")
cat.ActiveConnection = self.original_con_string
linked_tables = ()
for table in cat.Tables:
if table.Type == u"TABLE":
f = open(self.file_path + os.path.sep +
"Tablestruct_" + table.Name + ".txt", "w")
conn = client.CreateObject("ADODB.Connection")
conn.ConnectionString = self.original_con_string
rs = client.CreateObject("ADODB.Recordset")
conn.Open()
rs.Open("SELECT TOP 1 * FROM [%s];" % table.Name, conn)
for field in rs.Fields:
col = table.Columns[field.Name]
col_details = (col.Name, col.Type, col.DefinedSize,
col.Attributes)
property_dict = {}
property_dict["Autoincrement"] = (
col.Properties["Autoincrement"].Value)
col_details += property_dict,
f.write(repr(col_details) + "\n")
rs.Close()
conn.Close()
f.close()
if table.Type == u"LINK":
table_details = table.Name,
table_details += table.Properties(
"Jet OLEDB:Link DataSource").Value,
table_details += table.Properties(
"Jet OLEDB:Link Provider String").Value,
table_details += table.Properties(
"Jet OLEDB:Remote Table Name").Value,
linked_tables += table_details,
if linked_tables != ():
f = open(self.file_path + os.path.sep +
"linked_list.txt", "w")
for t in linked_tables:
f.write(repr(t) + "\n")
cat.ActiveConnection.Close()
Подобная обратная функция восстанавливает базу данных с помощью второй строки подключения.
Можно использовать Провайдер OLE DB ACE/струи и объект Соединения ADO метод OpenSchema для получения информации схемы как Recordset (который является спорным лучше, чем Набор, потому что это может быть фильтровано, отсортировано, и т.д.).
Базовая методология должна использовать adSchemaTables, чтобы получить базовые таблицы (не ПРЕДСТАВЛЕНИЯ), затем использовать каждый TABLE_NAME для выборки adSchemaColumns для ORDINAL_POSITION! DATA_TYPE! IS_NULLABLE! COLUMN_HASDEFAULT! COLUMN_DEFAULT! CHARACTER_MAXIMUM_LENGTH! NUMERIC_PRECISION! NUMERIC_SCALE.
adSchemaPrimaryKeys прост. adSchemaIndexes - то, где Вы найдете ограничения UNIQUE, не уверенные, можно ли их отличить от уникальных индексов, также названия ВНЕШНИХ КЛЮЧЕЙ для включения adSchemaForeignKeys набора строк, например, (псевдо код):
rsFK.Filter = "FK_NAME = '" & !INDEX_NAME & "'")
- наблюдайте за глюком, что Струйные 3.51 позволяют FK на основе неназванного PK (!!)
Названия Правил Проверки и ограничений CHECK могут быть найдены в adSchemaTableConstraints наборе строк, с помощью имени таблицы в вызове OpenSchema, затем использовать имя в вызове к adSchemaCheckConstraints набору строк, фильтр для CONSTRAINT_TYPE = 'ПРОВЕРКА' (глюк является ограничением под названием 'ValidationRule' +, Chr$ (0), настолько лучше всего для выхода из нулевых символов формируют имя). Помните, что правила Проверки ACE/струи могут быть или уровнем строки или уровнем таблицы (Ограничения CHECK всегда являются уровнем таблицы), таким образом, Вы, возможно, должны использовать имя таблицы в фильтре: поскольку adSchemaTableConstraints []. [].ValidationRule будет [].ValidationRule в adSchemaCheckConstraints. Другой глюк (подозреваемая ошибка) - то, что Поле является 255 широкими символами, таким образом, любое определение ПРАВИЛА/ОГРАНИЧЕНИЯ CHECK Проверки больше чем 255 символов будет иметь Нулевое значение.
adSchemaViews, для объектов Запроса Доступа на основе ИЗБРАННОГО SQL non-paramaterized DML, прост; можно использовать имя ПРЕДСТАВЛЕНИЯ в adSchemaColumns для получения деталей столбца.
ПРОЦЕДУРЫ находятся в adSchemaProcedures, будучи всеми другими ароматами объектов Запроса Доступа включая параметризованный ИЗБРАННЫЙ DML; для последнего я предпочитаю заменять синтаксис ПАРАМЕТРОВ CREATE PROCEDURE PROCEDURE_NAME в PROCEDURE_DEFINITION. Не делайте boterh, смотрящего в adSchemaProcedureParameters, Вы ничего не найдете: параметры могут быть перечислены при помощи объекта Каталога ADOX возвратить Команду ADO, например, (псевдо код):
Set Command = Catalog.Procedures(PROCEDURE_NAME).Command
затем перечислите Коммуникацию. Набор параметров для.Name.Type для DATA_TYPE, (.Attributes И adParamNullable) для IS_NULLABLE.Value для COLUMN_HASDEFAULT и COLUMN_DEFAULT.Size.Precision.NumericScale.
Для свойств ACE/Jet-specific, таких как сжатие Unicode необходимо использовать другой вид объекта. Например, Автонумерация Длинного целого в Доступе - говорит, может быть найден с помощью объекта Каталога ADO, например, (псевдо код):
bIsAutoincrement = Catalog.Tables(TABLE_NAME).Columns(COLUMN_NAME).Properties("Autoincrement").Value
Удача :)
Трудно сделать сценарии DDL / запросы в Доступе. Это может быть сделано, но Вы были бы более обеспечены просто создание копии базы данных - удаляющий все данные и уплотняющий его. Затем используйте копию этого для воссоздания базы данных в другом месте.
Проверьте docmd. Команда TransferDatabase. Вероятно, Ваш лучший выбор для интеграции сборки должен копировать структуру данных
В следующем C # описывается, как получить схему из файла .mdb.
Получить соединение с базой данных:
String f = "Provider=Microsoft.Jet.OLEDB.4.0;Data Source=" + "database.mdb";
OleDbConnection databaseConnection = new OleDbConnection(f);
databaseConnection.Open();
Получить имя каждой таблицы:
DataTable dataTable = databaseConnection.GetOleDbSchemaTable(OleDbSchemaGuid.Tables, new object[] { null, null, null, "TABLE" });
int numTables = dataTable.Rows.Count;
for (int tableIndex = 0; tableIndex < numTables; ++tableIndex)
{
String tableName = dataTable.Rows[tableIndex]["TABLE_NAME"].ToString();
Получить поля для каждой таблицы:
DataTable schemaTable = databaseConnection.GetOleDbSchemaTable(OleDbSchemaGuid.Columns, new object[] { null, null, tableName, null });
foreach (DataRow row in schemaTable.Rows)
{
String fieldName = row["COLUMN_NAME"].ToString(); //3
String fieldType = row["DATA_TYPE"].ToString(); // 11
String fieldDescription = row["DESCRIPTION"].ToString(); //27
}
}
Откуда берутся 3
, 11
и 27
? Я нашел их, проверив DataRow.ItemArray
с помощью отладчика. Кто-нибудь знает «правильный» способ?
Сравнить http://home.gci.net/~mike-noel/CompareEM-LITE/CompareEM.htm с радостью сгенерирует код VBA, необходимый для воссоздания MDB. Или код для создания различий между двумя MDB, чтобы вы могли обновить версию уже существующего BE MDB. Это немного странно, но работает. Обратите внимание, что он не поддерживает новые форматы ACE (Access2007), ACCDB и т. Д.
Я использую его все время.
(OneDayWhen редактировал одну треть правильно и две трети ошибочно)