[英]MS Access 2007 - Synchronizing two databases and keeping the record with the latest timestamp
使用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?
最好的祝福
我将假定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;
现在,您可以通过再次内部联接到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有时会允许您。 这篇文章 ,当你的详细信息,“这是记录不更新”的访问错误。 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并不完全支持该语法,因此您需要运行以下命令:
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表查询,将FullInfoQuery的结果粘贴到其自己的表中,然后基于该表编写一个UPDATE查询,其语法非常简单:
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
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.