如何在 Microsoft Access 中加快批量 'upsert'

How to speed up bulk 'upsert' in Microsoft Access

我正在使用 VBA 字典在 Access 中执行 'upsert'。我正在循环我的字典键,如果该键存在于 Access table 中,那么我会更新它。如果没有,它会插入它。然而,我的 table 包含 200k+ 行,这使得代码执行得非常慢(例如,5 分钟,甚至 5% 都没有完成),因为迭代需要在整个 table 中搜索 [=26] =](我的钥匙)。

有什么方法可以显着加快这个过程吗? 我的代码如下,如有任何帮助,我们将不胜感激。

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 & "'"

这用于查找密钥是否在数据库中。删除它(并简单地插入新数据)可以加快这个过程,并且可以在几秒钟内完成。有没有一种快速的方法来确定一个值是否已经在 table?

首先: 字典集合有多大。 (5、10 或 1000???)。

接下来,LOCID 是 table“MyTable”中的索引列。

如果LOCID已经是一个索引列,那么可以使用下面的代码。它应该将速度提高大约 100 倍或更多倍:

假定 table 不是链接的 table,但实际上是数据库中的 table。

请注意,您必须将有问题的 table 打开为“actable”——这是默认设置,所以我删除了 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,但你最好用 access 打开数据库,将 table 切换到设计模式,然后点击功能区 "indexs" 按钮。如果 LOCID 是主键,那么索引很可能被命名为 PrimaryKey。所以你需要索引的名称。

同上其他人的建议;从根本上不要做一个循环。执行操作查询(追加或更新)。

这是'programmer'和'database developer'之间最常见的区别……