使用每日更新的 Access 表自动刷新 SQL Server 后端

Posted

技术标签:

【中文标题】使用每日更新的 Access 表自动刷新 SQL Server 后端【英文标题】:Automatically refresh SQL Server backend with daily updated Access table 【发布时间】:2019-04-23 05:54:44 【问题描述】:

总结:我有一个本地 Access 数据库,其中包含订单,每天早上由自动 VBA 例程更新,由 Windows 任务启动。具体来说,每天早上 5:30 都会添加新订单,并使用本地 .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] = '---------';"

虽然 Access 文件中的链接表 dbo_ReiseMaster 包含更新的值,但它们并未上传到 SQL Server。

我如何确保本地 Access 表(无论我在哪些变体中处理数据)始终将更改传输到 SQL Server?

【问题讨论】:

您是否在 Access 查询中检查了 SELECT 部分 SELECT * FROM [ReiseMaster] WHERE NOT [Name of Employee] = '---------'; 实际返回记录? 嗨安德烈,是的,我已经检查过了。基本上有 10.000 条带有实际员工姓名的记录,并使用该语句返回。我也刚刚注意到,实际上没有插入链接表dbo_ReiseMaster。为了测试,我删除了链接表中具有名称的所有记录并在上面运行此语句。虽然 SELECT 部分返回了一条记录,但我在链接表中找不到此数据。 嗯,试试myDB.Execute "INSERT ...", dbFailOnError获取错误信息。 dbo_ReiseMaster 是否通过 ODBC 连接链接到 Access?还是您每次都使用 VBA 手动连接? dbo_ReiseMaster 是通过 ODBC 连接链接的,所以它应该是永久连接的。 【参考方案1】:

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

如果源表存在sql server端会怎样?

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

您现在可以通过 access 编写和使用标准 sql,并像使用本地表一样使用这两个表。

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

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

currentdb.Execute strSQL

所以,你可以对两张表使用sql,即使一张链接到sql server,但你必须使用链接表。您无需处理、查看或使用连接对象,因为它始终适用于一个连接对象。但是,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 服务器的表,以确保链接表一切正常(如果它显示数据 - 也许尝试编辑一行 - 移开,这将确保链接表是读/写的。

【讨论】:

好的,我明白你的意思了。鉴于这种解释,我的预期结果并没有真正确定。但是,我不确定“只需将表链接到服务器”是什么意思,因为我实际上使用了链接(导入 >> 链接)。 dbo_ReiseMaster 是一个链接表,这就是我尝试在此表上执行的原因,因为它是一个普通的 Access 表,如我上面的代码所示。 啊,好的,那么您可以 100% 省去代码中的任何“连接”内容。您可以使用内联 sql,或修改现有查询,但该查询将是标准查询 - 无需在代码中使用/混淆连接字符串。 在我的帖子中查看我的新编辑 + 建议 - 它为您提供了一些测试/尝试的东西。一旦你让 docmd.runSQL 工作正常,然后将代码更改为 CurrentDB.Execute - 摆脱事务和是/否提示以实际进行更新。

以上是关于使用每日更新的 Access 表自动刷新 SQL Server 后端的主要内容,如果未能解决你的问题,请参考以下文章

从 SQL Server DB 更新单独工作表中的数据后自动刷新 Excel 2007 数据透视表

Access中UPDATE语句一次要更新多个数据

Access中UPDATE语句一次更新多个数据

SQL自动增长列数据变动刷新的问题

SQL数据库中如何从A表自动更新数据到B表?

如何刷新绑定到已更新的 Access 数据库表的 DataGridView?