【问题标题】:MS Access 2007 - Synchronizing two databases and keeping the record with the latest timestampMS Access 2007 - 同步两个数据库并使用最新时间戳保存记录
【发布时间】:2017-07-20 20:43:37
【问题描述】:

使用 Access 2007,我有一个主数据库和几个从数据库。假设我有一个简单的表格:候选人。

在主数据库中

Id ;   Name    ;   Birthday   ;   Timestamp
01 ; Henri     ; 01-01-1911   ; 01-01-2017 

在从属数据库中

Id ;   Name    ;   Birthday   ;   Timestamp
01 ; Henry     ; 01-01-1911   ; 01-02-2017 

我需要的是,最新的操作记录替换主数据库中的先前记录。在本例中,从数据库中的记录将替换主数据库中的记录。

在我当前的解决方案中,我遍历记录集并比较时间戳。它有效,但我想知道是否有更有效和更快的解决方案?也许用 SQL?

最好的问候

【问题讨论】:

  • 数据宏或复制可能吗?
  • @Nathan_Sav 不幸的是,复制不再适用于 Access 2007 :-(
  • “主人”会被别人改变吗?如果没有,并且假设您包含代码以提醒用户是否将其系统时钟更改为较早的时间(并允许时区),您可以尝试以下操作:(1)从 Master 获取最新的时间戳; (2) 从“其他”数据库中获取时间戳较大的所有记录。
  • 假设您有一个匹配的 ID 主键字段,您可以将它们加入查询中,然后如果从属较晚,则更新主控?不确定您是否需要一个循环。
  • 如果保存为 2003 BE, 2003 Replica, 2007 FE Linked to replica。

标签: sql ms-access vba ms-access-2007


【解决方案1】:

假设

我将假设 ID 是所有数据库中的唯一标识符,并且从数据库中没有 ID 是 not 在主数据库中的。否则你会遇到问题,因为 slave1 可能会将 ID 7 分配给“Fred”,但 slave2 可能会将 ID 7 分配给“Thomas”。

联合查询

SELECT ID, Name, Birthday, Timestamp, 1 AS SlaveNum FROM Candidates_Slave1
UNION ALL
SELECT ID, Name, Birthday, Timestamp, 2 AS SlaveNum FROM Candidates_Slave2
UNION ALL
SELECT ID, Name, Birthday, Timestamp, 3 AS SlaveNum FROM Candidates_Slave3
UNION ALL
...

然后我会从该联合查询中编写一个 group by 查询,以获取每个 ID 及其最大时间戳。

组查询

SELECT ID, max(Timestamp) AS MaxTime FROM UnionQuery

然后将其加入 UnionQuery,并取最小(或最大)SlaveNum(以防多个从属具有相同的最大时间戳)。

加入查询

SELECT GroupQuery.ID, GroupQuery.MaxTime AS Timestamp, min(UnionQuery.SlaveNum) AS SlaveNum
FROM GroupQuery INNER JOIN UnionQuery ON
    GroupQuery.ID = UnionQuery.ID AND
    GroupQuery.MaxTime = UnionQuery.Timestamp;

现在你可以通过再次内联UnionQuery来获取最新的(从属)数据,并且你可以加入主候选人表并比较时间戳。添加一个 WHERE 子句,检查主表中是否存在小于我们的连接查询的时间戳:

全信息查询

SELECT Candidates_Master.ID, 
    Candidates_Master.Name AS Name_Master,
    Candidates_Master.Birthday AS Birthday_Master, 
    Candidates_Master.Timestamp AS Timestamp_Master, 
    UnionQuery.Name AS Name_Slave, 
    UnionQuery.Birthday AS Birthday_Slave,
    UnionQuery.Timestamp AS Timestamp_Slave
FROM (JoinQuery INNER JOIN UnionQuery 
    ON JoinQuery.ID = UnionQuery.ID AND JoinQuery.SlaveNum = UnionQuery.SlaveNum)
INNER JOIN Candidates_Master ON JoinQuery.ID = Candidates_Master.ID
WHERE Candidates_Master.Timestamp < UnionQuery.Timestamp;

最后,编写更新查询有时会很麻烦,因为严格来说,UPDATE 查询中不应该有 JOIN 子句,但 Access 有时可以让您这样做。 This post 在 Access 中收到“此记录集不可更新”错误时的详细信息。进行更新的 ANSI 方式是这样的:

更新查询

UPDATE Candidates_Master
SET (Name, Birthday, Timestamp) = (SELECT Name_Slave, Birthday_Slave, Timestamp_Slave FROM FullInfoQuery WHERE Candidates_Master.ID = FullInfoQuery.ID)
WHERE EXISTS (SELECT 1 FROM FullInfoQuery WHERE FullInfoQuery.ID = Candidates_Master.ID);

不幸的是,Access 并不完全支持该语法,因此您需要运行以下内容:

UpdateQuery_v2

UPDATE Candidates_Master
SET Name = (SELECT Name_Slave FROM FullInfoQuery WHERE Candidates_Master.ID = FullInfoQuery.ID),
Birthday = (SELECT Birthday_Slave FROM FullInfoQuery WHERE Candidates_Master.ID = FullInfoQuery.ID),
Timestamp = (SELECT Timestamp_Slave FROM FullInfoQuery WHERE Candidates_Master.ID = FullInfoQuery.ID)
WHERE EXISTS (SELECT 1 FROM FullInfoQuery WHERE FullInfoQuery.ID = Candidates_Master.ID);

但是因为它有这么多相关的子查询,所以它可能非常慢/效率低。试试看。一个常见的替代方法(无论如何对我来说)是编写一个 make table 查询将 FullInfoQuery 的结果粘贴到它自己的表中,然后基于该表编写一个 UPDATE 查询,语法非常简单:

UpdateQuery_v3

UPDATE Candidates_Master INNER JOIN tblFullInfoQuery ON Candidates_Master.ID = tblFullInfoQuery.ID
SET Candidates_Master.Name = tblFullInfoQuery.Name_Slave,
    Candidates_Master.Birthday = tblFullInfoQuery.Birthday_Slave,
    Candidates_Master.Timestamp = tblFullInfoQuery.Timestamp_Slave

【讨论】:

  • 非常感谢!同时我有一个不同的解决方案,但这似乎要快得多!非常感谢!!!!
猜你喜欢
  • 2013-01-28
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2017-12-23
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多