You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Access宽表转长表后关联查询返回不匹配记录问题排查

问题根因

1. 员工ID查询SQL语法错误,导致外键匹配完全失效

CODE1中构造员工ID查询的SQL遗漏了FirstName字段名,最终生成的SQL为:

SELECT ID FROM tbl_EmployeeInformation WHERE LastName = "传入的姓" AND "传入的名"

在Access SQL逻辑中,非空字符串常量会被判定为True,因此该条件等价于仅按LastName过滤员工。如果存在多名同姓员工,OpenRecordset默认返回查询结果的第一条记录ID,完全不校验名字,导致存入tbl_CompletedTrainings的Employee外键从根源上就是错的。
正确写法参考:

Set qryGetNameID = db.OpenRecordset("SELECT ID FROM tbl_EmployeeInformation WHERE LastName = " & Chr(34) & lname & Chr(34) & _
    " AND FirstName = " & Chr(34) & fname & Chr(34) & ";")

2. 重复调用AddNew生成脏数据

CODE1写入长表时连续调用了两次rsutab.AddNew:

rsutab.AddNew ' 第一次生成新行,未赋值
Debug.Print lname
Debug.Print fname
' 省略调试打印代码
rsutab.AddNew ' 第二次生成新行,丢弃上一行未保存的内容
rsutab("Employee") = qryGetNameID.Fields(0)
' 省略赋值逻辑
rsutab.Update

第一次AddNew生成的空行未赋值就被丢弃,部分场景下会生成多余的空值/默认值记录,也是数据异常的直接诱因之一,删除多余的第一次AddNew即可。

3. 培训ID偏差的原因

你观察到的培训ID比预期小2的问题,是因为培训ID查询SQL未指定排序规则,当存在近似匹配的培训名称(比如名称带多余空格、后缀),或查询结果默认按非主键字段排序时,OpenRecordset返回的第一条记录的AutoID就会和预期不符。
建议给查询SQL增加排序规则,同时加EOF判断避免匹配不到时报错:

Set qryGetTrainingNameID = db.OpenRecordset("SELECT AutoID FROM Trainings WHERE [Training Name] = " & Chr(34) & namevar & Chr(34) & " ORDER BY AutoID;")
If qryGetTrainingNameID.EOF Then
    ' 可在此处增加匹配不到的处理逻辑,比如跳过当前记录、打印日志
    GoTo NextLoop
End If

4. 空值判断逻辑错误

原代码的非空判断使用了Or逻辑:

If rsxtab.Fields(loopint) <> "" Or Not IsNull(rsxtab.Fields(loopint))

该逻辑会把Null值误判为有效内容,应该改为And逻辑:

If Not IsNull(rsxtab.Fields(loopint)) And rsxtab.Fields(loopint) <> ""

你看到的查询结果日期一致、其他字段不匹配的现象,正好对应上述问题:日期是直接从宽表中读取存入长表的,没有经过关联匹配,所以不会出错;而员工、培训字段依赖错误的外键查询逻辑存入,关联后自然返回不匹配的记录。


内容的提问来源于stack exchange,提问作者Christopher J. Joubert

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.10.04 21:24:05