我正在使用VBA词典在Access中执行“ upsert”。我正在循环我的字典键,如果该键存在于Access表中,那么我将对其进行更新。如果没有,它将插入它。但是,我的表包含200k +行,这使代码的执行速度非常慢(例如,完成5分钟,甚至没有完成5%),因为迭代需要在整个表中搜索“ LOC”(我的键)。
我有办法大大加快此过程吗? 我的代码在下面,感谢您的帮助。
Sub UpdateDatabase(dict As Object)
Dim db As Database
Dim rs As DAO.Recordset
Set db = OpenDatabase("C:\XXX\myDB.accdb")
Set rs = db.OpenRecordset("MyTable", dbOpenDynaset)
For Each varKey In dict.Keys()
'Table is searched for key
rs.FindFirst "[LOCID] = '" & varKey & "'"
If rs.NoMatch Then
'If the key was not found, insert it
rs.AddNew
rs!LOCID = varKey
rs![Status] = "To Start"
rs.Update
Else
'If the key was found, update its status
rs.Edit
rs![Status] = "Done"
rs.Update
End If
Next
rs.Close
db.Close
Application.StatusBar = False
End Sub
编辑:
我在上面的代码中发现了瓶颈。这是一行:
rs.FindFirst "[LOCID] = '" & varKey & "'"
这用于查找密钥是否在数据库中。删除它(并简单地插入新数据)可以加快过程,并且只需几秒钟即可完成。有没有一种快速的方法来确定表中是否已经存在值?
答案 0 :(得分:3)
首先: dict集合有多大。 (5、10或1000 ???)。
接下来,LOCID是该表“ MyTable”中的索引列。
如果LOCID已经是N索引列,则可以使用以下代码。它将使速度提高大约100倍或更多倍:
假定该表不是链接表,但实际上是数据库中的表。
请注意,您必须以“可操作的”方式打开有问题的表-这是默认设置,因此我删除了dbOpenDynaset)
此代码将解决问题:
Dim db As DAO.Database
Dim rs As DAO.Recordset
Set db = OpenDatabase("C:\XXX\myDB.accdb")
Set rs = db.OpenRecordset("MyTable") ' <--- note this!!!
rs.Index = "LOCID"
For Each varKey In dict.Keys()
'Table is searched for key
rs.Seek "=", varKey
If rs.NoMatch = True Then
'If the key was not found, insert it
rs.AddNew
rs!LOCID = varKey
rs![Status] = "To Start"
rs.Update
Else
'If the key was found, update its status
rs.Edit
rs![Status] = "Done"
rs.Update
End If
Next
rs.Close
db.Close
您还需要确定LOCID列上实际索引的名称。我在上面使用了LOCID,但最好打开具有访问权限的数据库,将表翻转到设计模式,然后单击功能区“索引”按钮。如果LOCID是主键,则很有可能将索引命名为PrimaryKey。因此,您需要索引的名称。
答案 1 :(得分:0)
这是“程序员”和“数据库开发人员”之间最常见的区别……