Автоматически обновлять серверную часть SQL Server ежедневно обновляемой таблицей доступа - PullRequest
1 голос
/ 23 апреля 2019

Сводка: У меня есть локальная база данных Access, которая содержит заказы и обновляется ежедневно утром с помощью автоматической подпрограммы VBA, запускаемой задачей Windows.Подробно, каждый день будут добавляться новые заказы, а существующие заказы будут обновляться новой информацией с использованием локального файла .csv, который удаляется в среде общих папок в 5:30 утра.

Теперь,У меня есть SQL Server, который должен быть в курсе, и точная копия локальной таблицы, в лучшем случае сразу после локального обновления.Это необходимо, потому что я использую SQL Server в качестве бэкэнда для инструмента автоматического распределения заказов, который будет использоваться около 50 сотрудниками в будущем.

То, что я пробовал: Я запускаю процедуру локального обновления полностью для локальной таблицы, которая является и всегда будет локальной, чтобы обеспечить плавный процесс обновления.Чтобы обновить таблицу SQL, я попытался реализовать ее, создав связанную таблицу, однако наборы данных не передаются на SQL Server.Это странно, потому что когда я вручную изменяю отдельные поля в связанной таблице, изменения немедленно отражаются в таблице SQL Server.Это только процессы на основе VBA, которые не обновляются в SQL Server.

Код:

Sub Sync_SQL()

Dim myDB As DAO.Database
Set myDB = CurrentDb

Dim strSQL As String

Dim qdf As QueryDef

' Erstellt einen temporären Query mit einem ODBC-Connection String zur Verbindung mit dem SQL Server
Set qdf = CurrentDb.CreateQueryDef("SyncDB")
qdf.Connect = "ODBC;Driver={SQL Server};server=XX.X.XXX.XX;database=OPM;uid=USID;pwd=PWD;"

' Löscht alle noch offenen Aufträge aus dem SQL-Server
qdf.SQL = "DELETE FROM [OPM].[dbo].[ReiseMaster] WHERE NOT [Name of Employee] = '---------';"
qdf.ReturnsRecords = False

' Führt den Query aus und misachtet dabei jegliche Dialogfelder
DoCmd.SetWarnings False
DoCmd.OpenQuery "SyncDB"
DoCmd.SetWarnings True

' Fügt aktuell offene Aufträge in den SQL-Server ein
myDB.Execute "INSERT INTO [dbo_ReiseMaster] SELECT * FROM [ReiseMaster] WHERE NOT [Name of Employee] = '---------';"

' Leert den Statistik-Table (sollte in Zukunft anders funktionieren)
qdf.SQL = "DELETE FROM [OPM].[dbo].[Statistics];"
qdf.ReturnsRecords = False

' Führt den Query aus und misachtet dabei jegliche Dialogfelder
DoCmd.SetWarnings False
DoCmd.OpenQuery "SyncDB"
DoCmd.SetWarnings True

' Lädt den Statistik-Table mit den neuen Werten hoch (sollte in Zukunft nur noch für neue Aufträge erfolgen, um Performance auch nach längerer Laufzeit der Datenbank gering zu halten)
myDB.Execute "INSERT INTO [dbo_Statistics] SELECT * FROM [Statistics];"

' Setzt die aktive Verbindung zurück und löscht den temporären Query
Set qdf = Nothing
myDB.QueryDefs.Delete "SyncDB"
myDB.QueryDefs.Refresh

End Sub

Результат: В частности, следующие изменения в связанной таблице не будут отражены в SQL Server:

myDB.Execute "INSERT INTO [dbo_ReiseMaster] SELECT * FROM [ReiseMaster] WHERE NOT [Name of Employee] = '---------';"

Хотя связанная таблица dbo_ReiseMaster в файле доступа содержит обновленные значения, они не загружаются вSQL Server.

Как я могу гарантировать, что локальная таблица Access (в каких вариантах я манипулирую данными) всегда будет передавать изменения в SQL Server?

1 Ответ

1 голос
/ 24 апреля 2019

Вы не можете использовать один объект подключения, а затем «надеяться», что доступ знает, какую таблицу использовать. Вы выполняете sql для одного объекта соединения, поэтому таблицы вставки и исходные файлы будут находиться в этом одном удаленном соединении. Вы не можете сделать это.

Что бы произошло, если бы исходная таблица существовала на стороне сервера sql?

Тем не менее, сбросьте все эти соединения с запросами. Просто свяжите таблицы с сервером.

Теперь вы можете писать и использовать стандартный sql из доступа и использовать обе таблицы, как если бы они были локальными.

Итак, вы можете пойти: dim strSQL в виде строки

strSQL = "INSERT INTO [ReiseMasterLinked] " & _
        "SELECT * FROM [ReiseMaster] WHERE NOT [Name of Employee] = '---------';"

currentdb.Execute strSQL

Таким образом, вы можете использовать sql для двух таблиц, даже если одна связана с сервером sql, но вы должны использовать связанные таблицы. Вы не имеете дела, не видите и не используете объект подключения, так как это всегда будет применяться к одному объекту подключения. Тем не менее, Access является ОЧЕНЬ особенным в том смысле, что вы можете написать sql, который включает в себя связанные таблицы и локальные таблицы - и он разрешит соединение, на котором основаны две таблицы (или фактически одна таблица не связана, является локальной, а другая - связанная таблица.

Редактировать

Вот еще один пример. Но ОБРАТИТЕ ВНИМАНИЕ, как я закомментировал команду .Execute и заменил ее на docmd.RunSQL.

Sub AppendTest()

  Dim strSQL     As String

  strSQL = "INSERT INTO tblHotelsSQL " & _
           "SELECT * FROM tblHotelsLOCAL WHERE NOT tblHotelsLOCAL.HotelName = '-----'"

  'CurrentDb.Execute strSQL, dbFailOnError
  DoCmd.RunSQL strSQL

End Sub

Это выполняется медленнее и оборачивает команду в транзакции - так что вы можете ответить да или нет на приглашение, но это дает НАМНОГО более подробное сообщение об ошибке относительно того, почему запрос не мог или не был выполнен. И снова обратите внимание, что строки подключения не требуются. Чтобы вышеприведенное сработало, можно сделать двойной двойной щелчок на связанной таблице с сервером SQL, чтобы убедиться, что связанная таблица работает нормально (и если она отображает данные - возможно, попробуйте отредактировать одну строку) - удалите ее, и это обеспечит связанная таблица предназначена для чтения / записи.

...