MS Access 2007 - 同步两个数据库并用最新的时间戳记录

MS Access 2007 - Synchronizing two databases and keeping the record with the latest timestamp

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

在主数据库中

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?

此致

假设

我假设 ID 是所有数据库中的唯一标识符,并且从数据库中没有 ID 是 不是 在主数据库中。否则你会遇到问题,因为 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
...

然后我会根据该联合查询编写一个分组查询,以获取每个 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;

现在可以再次通过inner join UnionQuery获取最新的(slave)数据,也可以join master Candidates table并比较时间戳。添加一个 WHERE 子句,检查主 table 中小于我们的连接查询的任何时间戳:

全信息查询

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 中出现 "this recordset is not updateable" 错误时的详细信息。执行更新的 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);

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

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