如何在MS Access中基于两张表自动填充Reports表字段?
解决方案:生成工人月度记录并支持产量录入
步骤1:创建工人-月份交叉查询(生成所有必要组合)
先生成Workers和Months的全组合(每个工人对应12个月),创建名为WorkerMonthCross的查询,SQL语句如下:
SELECT Workers.ID AS WorkerID, Workers.Name AS WorkerName, Months.ID AS MonthID, Months.MonthName FROM Workers, Months;
这个查询会自动生成所有工人与所有月份的配对记录,比如10个工人就会生成120条基础记录。
步骤2:关联现有Reports表生成可编辑查询
创建一个新查询,将WorkerMonthCross与Reports做左连接,关联WorkerID和MonthID,这样既保留已有的产量数据,也会显示未录入的空白记录。SQL语句:
SELECT DISTINCTROW WorkerMonthCross.WorkerID, WorkerMonthCross.WorkerName, WorkerMonthCross.MonthID, WorkerMonthCross.MonthName, Reports.Production FROM WorkerMonthCross LEFT JOIN Reports ON (WorkerMonthCross.MonthID = Reports.Month) AND (WorkerMonthCross.WorkerID = Reports.Worker);
- 打开查询的属性窗口,设置「唯一记录」为「是」,「唯一值」为「否」,确保
Production字段可编辑。 - 你可以直接用这个查询作为表单的数据源,在表单中填写
Production值。
步骤3:同步录入数据到Reports表
因为左连接查询的编辑不会自动同步到Reports表,需要通过两种方式处理:
方式一:用更新/追加查询批量同步
- 更新已有记录:创建更新查询,把查询中修改的
Production值同步到Reports表:
UPDATE Reports INNER JOIN WorkerMonthCross ON (Reports.Month = WorkerMonthCross.MonthID) AND (Reports.Worker = WorkerMonthCross.WorkerID) SET Reports.Production = [WorkerMonthCross_Reports].Production WHERE Reports.Worker = [WorkerMonthCross_Reports].WorkerID AND Reports.Month = [WorkerMonthCross_Reports].MonthID;
- 追加新记录:创建追加查询,把新增的
Production记录插入Reports表:
INSERT INTO Reports (Worker, Month, Production) SELECT WorkerMonthCross.WorkerID, WorkerMonthCross.MonthID, [WorkerMonthCross_Reports].Production FROM WorkerMonthCross LEFT JOIN Reports ON (WorkerMonthCross.MonthID = Reports.Month) AND (WorkerMonthCross.WorkerID = Reports.Worker) WHERE Reports.ID IS NULL AND [WorkerMonthCross_Reports].Production IS NOT NULL;
方式二:用表单事件自动同步
在表单的BeforeUpdate事件中添加VBA代码,实时同步数据:
Private Sub Form_BeforeUpdate(Cancel As Integer) Dim rs As Recordset Set rs = CurrentDb.OpenRecordset("SELECT * FROM Reports WHERE Worker = " & Me.WorkerID & " AND Month = " & Me.MonthID) If rs.EOF Then ' 无记录则追加 rs.AddNew rs!Worker = Me.WorkerID rs!Month = Me.MonthID rs!Production = Me.Production rs.Update Else ' 有记录则更新 rs.Edit rs!Production = Me.Production rs.Update End If rs.Close Set rs = Nothing End Sub
为什么你的之前方法不行?
- Access不支持多表复杂全外连接,所以会出现「ambiguous outer joins」错误;
- 拆分全外连接后的数据覆盖问题,是因为多表连接的逻辑没有先生成全组合,而是直接关联导致记录丢失;
- 无关联的查询不可更新,因为Access无法确定要将编辑内容写入哪个表,而左连接+
DISTINCTROW的方式可以明确编辑字段对应Reports表。
内容的提问来源于stack exchange,提问作者Ivan Beliakov
相关产品推荐
相关产品推荐

