处理AddNew密钥违规ADODB.Recordset

时间:2013-07-26 15:29:38

标签: excel excel-vba access-vba ado vba

我之前的标题引起了一些混乱......更新了 我最近在使用一些VBA桥接Excel和Access时遇到了这个问题。

所以我有一个包含我需要导入Access数据库的表的电子表格。 该表是通用的,如下所示。

EmployeeNumber  Unused_Field2   Unused_Field3
1                    @@@              @@@
2                    @@@              @@@
3                    @@@              @@@

Access中的唯一键设置为EmployeeNumber。

Excel中的我的VBA代码如下所示:

Sub test()
    Dim con As ADODB.Connection
    Dim rst As ADODB.Recordset

    strcon = "Provider=Microsoft.Jet.OLEDB.4.0;Data Source=c:\temp\mydb.mdb;"
    strsql = "SELECT * FROM Table1"

    Set con = New Connection
    Set rst = New Recordset

    con.Open strcon
    rst.Open strsql, strcon, adOpenStatic, adLockOptimistic

    For i = 0 To n
        On Error GoTo Errhdl
        rst.AddNew Array("Field1", "Field2", "Field3"), Array(Range("A" & i), Range("B" & i), Range("C" & i))
        On Error GoTo 0
    Next

    Exit Sub

Errhdl:

    Debug.Print "Record" & i & "caused an error"
    Resume Next

End Sub

不幸的是,数据质量不高,而且我经常会有重复的值导致密钥违规。 虽然我虽然Resume Next将清除错误允许另一个“AddNew”运行,但它没有。 一次密钥违规后的所有后续条目将返回相同的错误。

所以我的问题如下:

  1. 是否可以清除与记录集关联的错误? (为了记录,我试图获得“错误集合”并使用 方法Errors.Clear。这没有做到这一点。错误集合是特定于ADO对象的属性 - MSDN Errors Collection
  2. 这可以在不关闭并重新打开记录集的情况下完成吗?
  3. 如果需要进一步澄清,请告诉我们!

2 个答案:

答案 0 :(得分:0)

我不会使用错误处理(处理ADO错误很棘手),但在执行插入之前使用Find检查每次密钥是否已存在。如果密钥是索引字段(如您的描述所示),那么您可以考虑Seek,这对于大型数据集更有效。 (但是,Seek不适用于客户端游标 - adUseClient。)

这是我发现的代码片段,概述了步骤:

If Not .EOF Then
   .MoveFirst
   .Find "TPItemNbr='" & m_TPItemNbr & "'", , adSearchForward
End If
If .EOF Then
   .AddNew
   !TPItemVendorID = m_TPItemVendorID
   !TPItemNbr = m_TPItemNbr
   !TPItemEUOM = m_TPItemEUOM
   !TPItemUOMFactor = m_TPItemUOMFactor
   !TPItemPUOM = m_TPItemPUOM
   !TPItemDescription = m_TPItemDescription
   !TPItemUnitCost = m_TPItemUnitCost
   !TPItemUnitLabor = m_TPItemUnitLabor
   .Update

也就是说,在循环内执行每次查找,如果EOF(文件结束)为真,则表中的密钥不在表中,因此可以执行插入。

添加以响应有关复合键的更多信息。 我会创建一个Command对象并使用Execute。是的,它需要创建一个字符串,但您可以捕获并忽略关键违规的错误。

替代方案可能是

  • 运行单独的SQL语句以获取重复列表的记录集
  • 循环将数值存储在数组中
  • 每次检查数组时执行AddNew

这对我来说似乎很麻烦,特别是搜索数组的方面。

  • 追求评论中链接的多重查找方法。

答案 1 :(得分:0)

因此,如果Recordset.AddNew遇到错误,我找到了解决方案。 诀窍是使用CancelUpdate - MSDN

还可以使用Status属性来检查操作是否成功。

示例代码为:

Sub test()
    Dim con As ADODB.Connection
    Dim rst As ADODB.Recordset

    strcon = "Provider=Microsoft.Jet.OLEDB.4.0;Data Source=c:\temp\mydb.mdb;"
    strsql = "SELECT * FROM Table1"

    Set con = New Connection
    Set rst = New Recordset

    con.Open strcon
    rst.Open strsql, strcon, adOpenStatic, adLockOptimistic

    For i = 0 To n
        On Error GoTo Errhdl
        rst.AddNew Array("Field1", "Field2", "Field3"), Array(Range("A" & i), Range("B" & i), Range("C" & i))
        On Error GoTo 0
    Next

    Exit Sub

Errhdl:

    Debug.Print "Record" & i & "caused an error"
    If rst.Status <> 0 Then
        rst.CancelUpdate
    End If
    Resume Next

End Sub