使用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
我需要的是,最新的操纵记录取代了主DB中的前一条记录。在此示例中,来自从数据库的记录将替换主数据库中的记录。
在我目前的解决方案中,我遍历记录集并比较时间戳。它有效,但我想知道是否有更高效,更快的解决方案?也许用SQL?
祝你好运
答案 0 :(得分:0)
我将假设ID是所有数据库中的唯一标识符,并且主数据库中不的从属数据库中没有ID。否则你会遇到问题,因为slave1可能会将ID 7分配给" Fred"但是slave2可能会将ID 7分配给#34; 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来获取最新(从属)数据,并且可以加入主Candidates表并比较时间戳。添加一个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详细说明当你得到&#34;这个记录集不可更新时#34; 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 table查询来将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