В Excel VBA запустить SQL оператор "SELECT ... INTO ... IN ...." - PullRequest
0 голосов
/ 03 октября 2018

Кажется, я не могу найти какую-либо хорошую ссылку или пример того, как заставить это работать.У меня есть база данных, которая хранится в AS / 400 (моя локальная база данных MS Access [хранится на сетевом диске] имеет связанные таблицы с 400, используя ODBC / DSN).Моя утилита прекрасно работает, пропуская операторы SQL через Access для извлечения данных из 400, используя связанные таблицы.Проблема в том, что с некоторыми более крупными отчетами и тем, что 400 находится в нескольких штатах, запуск отчетов может занять несколько часов.Решение этой проблемы заключается в создании локальной «копии» необходимых таблиц с набором данных, который имеет отношение к отчетам, а это значительно меньший набор данных.Очевидно, у этого есть недостаток - не «живые» данные, но я могу с этим смириться.В конечном итоге я хочу собрать соответствующие данные из связанной таблицы и сохранить их в отдельной базе данных, которая является локальной для клиента, чтобы ее можно было использовать в автономном / автономном режиме и для увеличения скорости отчета.

база данных, хранящаяся в сети = DB1 (таблица привязана к AS / 400), база данных, хранящаяся на локальном клиенте = DB2 (соответствующий набор данных, созданный в соответствии с SQL ниже, несвязанные таблицы, названные так же, как связанные таблицы)

нижеявляется оператором SQL, который я пытаюсь заставить работать с использованием VBA & DAO

SELECT 
    DB1_TABLEA.FIELD1, 
    DB1_TABLEA.FIELD2, 
    DB1_TABLEA.FIELD3, 
    DB1_TABLEA.FIELD4, 
    DB1_TABLEA.FIELD5, 
    DB1_TABLEA.FIELD6, 
    DB1_TABLEA.FIELD7, 
    DB1_TABLEA.FIELD8 
INTO 
    DB1_TABLEA IN 'Local_DB_Copy.accdb'    <== Creating non-linked copy 
FROM 
    DB1_TABLEA
WHERE 
    (
        ((DB1_TABLEA.FIELD4) Like 99999) 
        AND 
        ((DB1_TABLEA.FIELD6)="02" Or (DB1_TABLEA.FIELD6)="22")
    )
;

У меня уже есть программа, которая работает нормально и возвращает / обрабатывает данные из базы данных AS / 400.Мне просто нужно, чтобы вышесказанное работало так, чтобы у людей была возможность запустить локальную копию, которая будет обрабатываться намного быстрее.

Ниже приведен код, который я пробовал, но, конечно, он не работает или яздесь бы не было.

Sub gCreateLocalDBTables()
    Dim DBPath As String
    Dim LocalDBPath As String
    Dim sSQL As String
    Dim DB As DAO.Database
    Dim DB2 As DAO.Database
    Dim RS As DAO.Recordset
        LocalDBPath = "AS400_Local.accdb"
        sSQL = "SELECT DB1_TABLEA.FIELD1, DB1_TABLEA.FIELD2, DB1_TABLEA.FIELD3, DB1_TABLEA.FIELD4, DB1_TABLEA.FIELD5, DB1_TABLEA.FIELD6, DB1_TABLEA.FIELD7, DB1_TABLEA.FIELD8 INTO DB2_TABLEA IN '" & LocalDBPath & "' FROM DB1_TABLEA WHERE (((DB1_TABLEA.FIELD4) Like 99999) AND ((DB1_TABLEA.FIELD6)='02' Or (DB1_TABLEA.FIELD6)='22'));"
        Set DB = OpenDatabase(LocalDBPath, False, False)
        DB.TableDefs.Delete ("DB2_TABLEA")
        DB.Close
        DBPath = Interaction.GetSetting("Cust_Tools", "Settings\Report_Planning", "400DB_Location")
        Set DB2 = OpenDatabase(DBPath, False, False)
        Set RS = DB2.OpenRecordset(sSQL)
        RS.Close
        DB2.Close
        Set RS = Nothing
        Set DB = Nothing
        Set DB2 = Nothing
End Sub

Я знаю, что SQL работает, так как я тестировал его изнутри MS Access.Я просто не могу найти информацию о том, как заставить его работать при передаче из Excel VBA

1 Ответ

0 голосов
/ 03 октября 2018

Нельзя назначить запрос действия, например, запрос таблицы составления (т. Е. SELECT с вызовом INTO) для набора записей.Подумайте о выполнении запросов действий DROP и SELECT ... INTO до открытия набора записей в локальной таблице.Кроме того, неясно, почему вы открываете вторую базу данных или на что указывает путь.Ниже открывается набор записей для данных мэйнфрейма:

Set DB = OpenDatabase(LocalDBPath, False, False)

DB.Execute "DROP TABLE DB2_TABLEA", dbFailOnError
DB.Execute sSQL, dbFailOnError

Set RS = DB.OpenRecordset("SELECT * FROM DB2_TABLEA")

Кроме того, в запросе make-таблицы предложение IN не требуется, поскольку вы в настоящее время подключены к той самой базе данных, в которой выполняется действие.на.Просто удалите его ( '"& LocalDBPath &"' ).Кроме того, LIKE выражения без подстановочных знаков и чисел следует заменить на =

SELECT 
    DB1_TABLEA.FIELD1, 
    DB1_TABLEA.FIELD2, 
    DB1_TABLEA.FIELD3, 
    DB1_TABLEA.FIELD4, 
    DB1_TABLEA.FIELD5, 
    DB1_TABLEA.FIELD6, 
    DB1_TABLEA.FIELD7, 
    DB1_TABLEA.FIELD8 
INTO 
    DB2_TABLEA 
FROM 
    DB1_TABLEA
WHERE 
    (
        ((DB1_TABLEA.FIELD4) = 99999) 
        AND 
        ((DB1_TABLEA.FIELD6)='02' OR (DB1_TABLEA.FIELD6)='22')
    )
;

Фактически, рассмотрите возможность сохранения запроса в базе данных MS Access (Лента -> Создать -> Дизайн запроса ->SQL View) и вызывайте его как именованный объект, избегая длинных SQL в VBA.

DB.Execute "DROP TABLE DB2_TABLEA", dbFailOnError
DB.Execute "mySavedQuery", dbFailOnError

Set RS = DB.OpenRecordset("SELECT * FROM DB2_TABLEA")
...