Заполнение текущей базы данных записями из другой базы данных при определенных условиях - PullRequest
0 голосов
/ 04 июня 2018

Во-первых, я очень новичок в кодировании, поэтому, пожалуйста, потерпите меня, во-вторых,

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

Мой текущий код выглядит следующим образом

varPrimaryKey = InputBox("Specify primary key:")
strPrimaryKey = module1.Item1

If Not varPrimaryKey = "" Then
    MsgBox ("Get data from: " & varPrimaryKey)

    If Not (tdf.Name Like "MSys*" Or tdf.Name Like "~*") Then
        For Each tdf In externalDb.TableDefs
            For Each fld In tdf.Fields

                db.Execute ("INSERT INTO CurrentDb.fld.Name SELECT fld.Name FROM tdf.Name WHERE fld.Name = 'Value' AND varPrimaryKey = 'Value'")

            Next fld
        Next tdf
    End If
End If

Прямо сейчасЯ получаю ошибку несоответствия типов из .CurrentDb, но у меня есть ощущение, что с этим кодом тоже что-то не так, просто не могу это понять.Если бы кто-то мог помочь, я был бы очень признателен!

Ответы [ 2 ]

0 голосов
/ 04 июня 2018

Пересмотрите весь этот подход.Для нужд пользовательского приложения базы данных не должны копироваться друг на друга, как собраны из приведенного выше комментария:

Я имел в виду, что я хотел бы извлечь ВСЕ записи из ВСЕХ таблиц, которые имеют тот же идентификатор первичного ключа, что итот, который пользователь ввел в поле ввода

Одним из центральных принципов реляционной базы данных является предотвращение дублирования данных.Кроме того, если пользователи добавляют / редактируют данные, они отражаются в реальном времени в системе.Передача данных между базами данных должна выполняться только для целей миграции, когда одна должна быть заархивирована, а другая - для производства.


С учетом сказанного рассмотрите следующие шаги для создания своего пользовательского приложения:

  1. Свяжите все необходимые таблицы из сетевой базы данных.Диалоговое окно графического интерфейса пользователя позволяет Выбрать все функцию или удержание SHIFT и / или CTRL для нескольких таблиц.

  2. Buildвременная таблица для хранения первичного ключа текущего пользователя и вставки значения данных через VBA.Это единственная таблица для хранения данных (одна колонка / одна структура строк) в базе данных приложения.См. Ниже шаги:

    Создать таблицу с кодом или с помощью дизайна таблицы (одна строка / один столбец)

    CREATE TABLE TmpPrimaryKey (
        PrimaryID Long
    )
    

    Добавить, используя пользовательский ввод, как показано ниже с параметризациейс VBA.Этот код должен регулярно запускаться для любых изменений в PK.В идеале запускайте его при запуске приложения.

    Dim qdef As QueryDef
    Dim strSQL As String
    Dim varPrimaryKey As Variant
    
    varPrimaryKey = InputBox("Specify primary key:")
    
    ' CLEAN OUT TEMP TABLE
    CurrentDb.Execute "DELETE FROM TmpPrimaryKey", dbFailOnError
    
    ' APPEND TO TEMP TABLE 
    strSQL = "PARAMETERS [PkParam] LONG;" _ 
                & " INSERT INTO TmpPrimaryKey (PrimaryID) VALUES ([PkParam])"
    
    Set qdef = CurrentDb.CreateQueryDef("", strSQL)
    qdef![PkParam] = varPrimaryKey
    qdef.Execute dbFailOnError
    
    Set qdef = Nothing
    
  3. Создайте отфильтрованный запрос для каждой связанной таблицы, выравнивая по TmpPrimaryKey (т. Е. Целевой первичный ключ).При этом пользователь увидит только такие записи.Используйте эти запросы для источников записей форм / отчетов или наборов записей модулей.

    Запросы могут использовать предложения JOIN, IN, EXISTS, такие как приведенные ниже примеры отдельных операторов SQL.Таблицы ниже будут связанными таблицами из сетевой базы данных (шаг № 1).

    Query1

    SELECT src.* 
    FROM [Table1] src
    INNER JOIN TmpPrimaryKey tmp ON src.ID = tmp.PrimaryID;
    

    Query2

    SELECT src.* 
    FROM [Table2] src
    WHERE src.ID IN (SELECT PrimaryID FROM TmpPrimaryKey);
    

    Query3

    SELECT src.* 
    FROM [Table3] src
    WHERE EXISTS
       (SELECT 1 FROM TmpPrimaryKey tmp WHERE src.ID = tmp.PrimaryID);
    

    Поскольку у вас потенциально есть много таблиц, создавайте выше запросы SQL в цикле VBA, используя TableDefs и QueryDefs .ПРИМЕЧАНИЕ: подпрограмма ниже цикла для создания запросов должна запускаться только один раз .

    Dim tdef As TableDef
    Dim qdef As QueryDef
    Dim strSQL As String
    
    ' LOOP THROUGH ALL TABLES OF APP DB (I.E., LINKED TABLES)
    For Each tdef in CurrentDb.TableDefs
        If tdef.Name <> "TmpPrimaryKey" And tdef.Name Not Like "MSys*" Then
            ' ASSUMING EACH TABLE'S PK IS NAMED ID
            strSQL = "SELECT src.* FROM [" & tdef.Name & "] src"  _
                      & " INNER JOIN TmpPrimaryKey tmp ON src.ID = tmp.PrimaryID;"    
    
            ' NAME EACH QUERY SAME AS TABLE WITH "Q_PK" SUFFIX
            Set qdef = CurrentDb.CreateQueryDef(tdef.Name & "Q_PK", strSQL)
            Set qdef = Nothing
        End If
    Next tdef
    
    Set tdef = Nothing
    

    Опять же, установите все необходимые объекты приложения (формы, отчеты, модули и т. Д.), Чтобы они указывали на этизапросы как источники данных, а не связанные таблицы, содержащие все данные.Запросы должны обновляться, чтобы пользователь мог добавлять / редактировать записи.


Оттуда раздайте копии этой базы данных приложения всем пользователям в архитектуре с внешним интерфейсом и бэкэндом, поддерживая одна централизованная и нормализованная база данных и множество файлов приложений, которые содержат нет данных (кроме, конечно, значения временного PK).

Split Database Design

0 голосов
/ 04 июня 2018

Вы просто ссылаетесь на таблицу, в которую хотите ВСТАВИТЬ.Что вам нужно, это путь к другой БД.Нужно объединить переменные.Вы не показываете объявление и установку переменных db, tdf, fld, externalDB.Нужно поменять местами If и первые For строки.Ваш INSERT SELECT не будет работать так, как вы думаете, если вы действительно не хотите, чтобы каждое поле было вставлено в свою запись.Обратите внимание:

For Each tdf In CurrentDb.TableDefs
    If Not (tdf.Name Like "MSys*" Or tdf.Name Like "~*") Then

        CurrentDb.Execute ("INSERT INTO [" & tdf.Name & "] SELECT * FROM [" & tdf.Name & _
        "] IN 'other db path\filename.accdb' WHERE [Value] = '" & varPrimaryKey & "'")

    End If
Next tdf

Однако поля автонумерации будут мешать этому простому INSERT SELECT.Кроме того, поля в обеих таблицах должны быть расположены в одинаковом порядке в дизайне таблицы.

Value является зарезервированным словом и в действительности следует избегать использования зарезервированных слов в качестве имен для чего-либо.Если Value является числовым типом данных, тогда исключите разделители апострофов.

Почему этот MsgBox?

Но тогда зачем все эти усилия, а не просто ссылки на бэкэнд-таблицы?

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...