插入MS访问

我需要为MS-Access 2000编写一个SQL查询,以便一行更新(如果存在),但如果不存在则插入。 (我相信这被称为“upsert”)

如果行存在…

UPDATE Table1 SET (...) WHERE Column1='SomeValue' 

如果它不存在…

 INSERT INTO Table1 VALUES (...) 

这可以在一个查询中完成吗?

我通常首先运行插入语句,然后检查是否发生错误3022,这表明行已经存在。 所以像这样的东西:

 On Error Resume Next CurrentDb.Execute "INSERT INTO Table1 (Fields) VALUES (Data)", dbFailOnError If Err.Number = 3022 Then Err.Clear CurrentDb.Execute "UPDATE Table1 SET (Fields = Values) WHERE Column1 = 'SomeValue'", dbFailOnError ElseIf Err.Number <> 0 Then 'Handle the error here Err.Clear End If 

EDIT1:
我想提一下,我在这里发布的是一个非常常见的解决scheme,但是您应该意识到计划错误并将它们用作程序正常stream程的一部分通常被认为是一个坏主意,特别是如果有其他方法达到相同的结果。 感谢RolandTumble指出这一点。

假设在Column1上有一个唯一的索引,你可以使用一个DCountexpression式来决定你是否有零或一行Column1 ='SomeValue' 。 然后基于该计数的INSERTUPDATE

 If DCount("*", "Table1", "Column1 = 'SomeValue'") = 0 Then Debug.Print "do INSERT" Else Debug.Print "do UPDATE" End If 

我更喜欢这种方法,首先尝试一个INSERT ,捕获3022密钥违规错误,并对错误进行UPDATE 。 但是我不能从我的方法中获得巨大的利益。 如果您的表包含自动编号字段,避免插入失败将阻止您无用地花费下一个自动编号值。 我也可以避免在不需要的时候创build一个INSERTstring。 Access Cookbook告诉我,string连接在VBA中是一个相当昂贵的操作,所以我寻找避免构buildstring的机会,除非实际需要。 这种方法也将避免为不需要的INSERT创build一个锁。

但是,这些原因都不是非常有吸引力的。 诚然,我认为在这种情况下,我的偏好可能是关于什么对我来说是“正确的”。 我同意@ David-W-Fenton的这个评论以前的一个堆栈溢出问题 : “最好是编写你的SQL,所以你不要试图添加已经存在的值 – 也就是说,防止错误发生在第一个而不是依靠数据库引擎来保存你自己。“

你不需要知道错误。 相反,只需运行INSERT语句,然后检查

 CurrentDb.RecordsAffected 

它将是1或0,具体情况。

注意:针对CurrentDB执行是不好的做法。 最好将数据库捕获到本地variables:

 Dim db As DAO.Database Set db = CurrentDb db.Execute(INSERT...) If db.RecordsAffected = 0 Then db.Execute(UPDATE...) End If 

可以通过使用带有LEFT JOINUPDATE查询模拟Access中的upsert。

 update b left join a on b.id=a.id set a.f1=b.f1 , a.f2=b.f2 , a.f3=b.f3 

见: https : //www.experts-exchange.com/questions/28713136/可以

如果表具有唯一的密钥,则可以使用“upsert”。

智能访问这个老的提示是我的最爱之一:

用一个查询更新和附加logging

通过Alan Biggs

您是否知道可以在Access中使用更新查询来同时更新和添加logging? 如果您有两个版本的表tblOld和tblNew,并且您想要将来自tblNew的更改集成到tblOld中,这非常有用。

按着这些次序:

创build一个更新查询并添加这两个表。 通过将tblNew的关键字段拖到tblOld的匹配字段来join这两个表。

  1. 双击关系并select包含来自tblNew的所有logging的连接选项,并select仅包含来自tblOld的所有logging的连接选项。

  2. 从tblOld中select所有的字段,并将它们拖到QBE网格上。

  3. 对于每个字段,在tblNew.FieldName中的更新到单元格types中,其中FieldName与tblOld的字段名称匹配。

  4. 从视图菜单中select查询属性,并将唯一logging更改为假。 (这将closuresSQL视图中的DISTINCTROW选项,如果将其保留,则只会在结果中获得一条空白logging,但每个新logging需要一条空白logging才能添加到tblOld。

  5. 运行查询,你会看到对tblNew的改变现在在tblOld。

这只会将logging添加到已添加到tblNew的tblOld。 tblOld中不存在的logging仍然保留在tblOld中。