Как извлечь схему Доступа (.mdb) база данных?

Благодаря н.м. Свойства проекта VisualGDB- Настройки Makefile -Дополнительные входные данные компоновщика: -ldl, и он разработан

26
задан David-W-Fenton 17 December 2009 в 05:19
поделиться

7 ответов

Возможно сделать немного с 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
22
ответ дан 28 November 2019 в 06:53
поделиться

Если Вы рады использовать что-то другое, чем чистый Доступ 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()

Подобная обратная функция восстанавливает базу данных с помощью второй строки подключения.

6
ответ дан 28 November 2019 в 06:53
поделиться

Можно использовать Провайдер 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

Удача :)

5
ответ дан 28 November 2019 в 06:53
поделиться

Трудно сделать сценарии DDL / запросы в Доступе. Это может быть сделано, но Вы были бы более обеспечены просто создание копии базы данных - удаляющий все данные и уплотняющий его. Затем используйте копию этого для воссоздания базы данных в другом месте.

1
ответ дан 28 November 2019 в 06:53
поделиться

Проверьте docmd. Команда TransferDatabase. Вероятно, Ваш лучший выбор для интеграции сборки должен копировать структуру данных

1
ответ дан 28 November 2019 в 06:53
поделиться

В следующем 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 с помощью отладчика. Кто-нибудь знает «правильный» способ?

8
ответ дан 28 November 2019 в 06:53
поделиться

Сравнить http://home.gci.net/~mike-noel/CompareEM-LITE/CompareEM.htm с радостью сгенерирует код VBA, необходимый для воссоздания MDB. Или код для создания различий между двумя MDB, чтобы вы могли обновить версию уже существующего BE MDB. Это немного странно, но работает. Обратите внимание, что он не поддерживает новые форматы ACE (Access2007), ACCDB и т. Д.

Я использую его все время.

(OneDayWhen редактировал одну треть правильно и две трети ошибочно)

2
ответ дан 28 November 2019 в 06:53
поделиться
Другие вопросы по тегам:

Похожие вопросы: