Access中SQL复制表数据报错:目标表已存在,如何保留数据集?
解决Access中向已有带主键的表导入数据的问题
你遇到的问题很典型——SELECT * INTO语句的作用是创建一个新表并把查询结果插入进去,所以当目标表_tmp_table2已经存在时,自然会报“已存在”的错误。要往已存在的表(还带主键)里追加数据且保留原有记录,得换用INSERT INTO ... SELECT ...的写法,还要注意主键冲突的问题,下面分情况给你方案:
1. 确定源数据无重复主键,直接追加
如果能保证_tmp_table里的主键值在_tmp_table2中完全没有重复,可以直接用最简单的插入语句:
CurrentDb.Execute "INSERT INTO _tmp_table2 SELECT * FROM _tmp_table"
不过更稳妥的方式是明确指定字段列表(避免因表结构字段顺序变化导致的错误),比如:
CurrentDb.Execute "INSERT INTO _tmp_table2 (id, name, create_time) SELECT id, name, create_time FROM _tmp_table"
这里把id(主键)、name、create_time换成你实际的字段名就行。
2. 源数据可能有重复主键,跳过重复记录
如果源表和目标表存在主键重复的情况,直接插入会触发主键冲突报错,这时候可以用WHERE NOT EXISTS子句过滤掉已存在的记录:
CurrentDb.Execute "INSERT INTO _tmp_table2 (id, name, create_time) " & _ "SELECT t1.id, t1.name, t1.create_time " & _ "FROM _tmp_table t1 " & _ "WHERE NOT EXISTS (SELECT 1 FROM _tmp_table2 t2 WHERE t2.id = t1.id)"
这个语句会只插入_tmp_table2中没有的新记录,自动跳过主键重复的条目。
3. 重复主键时更新旧记录,无则插入(Upsert)
如果希望主键重复时更新目标表的对应记录,而不是跳过,Access没有直接的MERGE语句,得分成两步执行:先更新已有记录,再插入新记录:
' 第一步:更新目标表中与源表主键重复的记录 CurrentDb.Execute "UPDATE _tmp_table2 t2 INNER JOIN _tmp_table t1 ON t2.id = t1.id " & _ "SET t2.name = t1.name, t2.create_time = t1.create_time" ' 第二步:插入目标表中没有的新记录 CurrentDb.Execute "INSERT INTO _tmp_table2 (id, name, create_time) " & _ "SELECT t1.id, t1.name, t1.create_time " & _ "FROM _tmp_table t1 " & _ "WHERE NOT EXISTS (SELECT 1 FROM _tmp_table2 t2 WHERE t2.id = t1.id)"
额外注意事项
- 一定要确保源表和目标表的字段类型完全匹配,尤其是主键字段的类型和长度,否则会插入失败
- 执行语句时可以加上
dbFailOnError参数,这样如果执行出错会抛出具体错误信息,方便调试:CurrentDb.Execute "INSERT ...", dbFailOnError - 如果目标表还有其他约束(比如外键、非空字段),要确认源数据满足这些约束条件,否则也会报错
内容的提问来源于stack exchange,提问作者dmorgan20
相关产品推荐
相关产品推荐

