使用每日更新的访问 table 自动刷新 SQL 服务器后端

Automatically refresh SQL Server backend with daily updated Access table

总结: 我有一个包含订单的本地 Access 数据库,每天早上由 VBA 自动例程更新,由 Windows 任务。详细地说,每天都会添加新订单,并使用本地 .csv 文件更新现有订单的新信息,该文件在早上 5:30am 放在共享文件夹环境中。

现在,我有一个需要更新的 SQL 服务器和本地 table 的精确副本,最好是在本地更新完成后。这是必要的,因为我使用 SQL 服务器作为自动订单分发工具的后端,将来会有大约 50 名员工使用。

我已经尝试过: 我是 运行 完全在本地 table 上的本地更新例程,它现在是并且永远是本地的以确保更新过程顺利进行。为了更新 SQL table 我试图通过创建链接 table 来实现它,但是,数据集没有传输到 SQL 服务器。这很奇怪,因为当我在链接 table 中手动更改单个字段时,更改会立即反映在 SQL 服务器 table 中。只有基于 VBA 的进程未在 SQL 服务器中更新。

代码:

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

结果: 特别是,以下对链接 table 的更改不会反映在 SQL 服务器中:

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

虽然 Access 文件中的链接 table dbo_ReiseMaster 包含更新的值,但它们没有上传到 SQL 服务器。

我如何确保本地访问 table(无论我以何种方式处理数据)总是将更改传输到 SQL 服务器?

您不能使用单个连接对象然后“希望”access 知道要使用什么 table。您在单个连接对象上执行 sql,因此插入和源 table 将驻留在那个远程连接上。你不能那样做。

如果源 table 存在 sql 服务器端会怎样?

但是,转储所有查询连接内容。只需 link table 到服务器。

您现在可以编写和使用来自 access 的标准 sql,并像在本地一样使用两个 table。

所以,你可以去: 将 strSQL 调暗为字符串

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

currentdb.Execute strSQL

因此,您可以对两个 table 使用 sql,即使一个 linked 到 sql 服务器,但您必须使用 linked tables。您无需处理、查看或使用连接对象,因为它始终适用于一个连接对象。但是,Access 非常特殊,因为您可以编写包含 linked tables 和本地 tables 的 sql - 它将解析两个 tables 是基于(或者事实上,一个 table 不是 linked 是本地的,另一个是 linked table.

编辑

这是另一个例子。但请注意我是如何注释掉 .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

这 运行 速度较慢,并将命令包装在一个事务中 - 因此您可以对提示回答是或否,但它会提供更详细的错误消息,说明查询无法执行的原因,或者没有 运行。再次注意不需要连接字符串。要使上述工作正常,可以快速双击 linked table 到 SQL 服务器以确保 linked table 全部正常工作很好(如果它显示数据 - 也许尝试编辑一行 - 离开,这将确保 linked table 是 read/write.