使用多个条件在 ADO Recordset 中查找记录的最有效方法? (VB6)
Most efficient way to find record in ADO Recordset with multiple criteria? (VB6)
我正在将一些旧的遗留访问代码转换为 SQL,用于我们的遗留程序,在该程序中我们根据数千条记录的数据创建报告。我们使用多个记录集来访问不同的 records/tables。以前(在访问中),我们使用 Recordset.Seek 函数在记录集中找到所需的记录。这样做可以让我们在几秒钟内获得我们想要的数据。
在使用 ADO 记录集而不是 DAO 将其转换为与 SQL 一起使用时,我发现大多数人建议简单地将记录集设置为等于新记录集的查询,该查询将 return想要的记录。到目前为止,这是执行此操作的最有效方法,但这仍然需要最多 2 分钟才能获得需要几秒钟才能访问的相同数据。
我看到 ADO Recordset 也有一个 .seek 函数,但我在尝试实现它以进行比较时遇到了问题 speed/accuracy。如果这是更好的方法,我如何 create/set 记录集的索引,以及如何知道索引的名称?
谢谢!
您只能将 Seek
用于来自 JET OLEDB 提供程序的服务器端记录集。您可以使用 rs.Supports(adSeek)
.
之类的记录集测试 Seek
是否可用
我通常对客户端记录集所做的是使用如下函数构建内存中索引"by hand":
Public Function InitIndexCollection( _
rs As Recordset, _
sFld As String, _
Optional Fld2 As String, _
Optional Fld3 As String, _
Optional ByVal HasDuplicates As Boolean, _
Optional RetVal As Collection) As Collection
Const FUNC_NAME As String = "InitIndexCollection"
Dim oFld As ADODB.Field
Dim oFld2 As ADODB.Field
Dim oFld3 As ADODB.Field
Dim vBmk As Variant
Dim pCol As Collection '-- IVbCollection that doesn't raise duplicate error on Add
Set RetVal = New Collection
With rs
If .RecordCount > 0 Then
On Error Resume Next
vBmk = rs.Bookmark
On Error GoTo 0
.MoveFirst
Set oFld = .Fields(sFld)
If LenB(Fld2) <> 0 Then
Set oFld2 = .Fields(Fld2)
End If
If LenB(Fld3) <> 0 Then
Set oFld3 = .Fields(Fld3)
End If
If HasDuplicates Then
On Error Resume Next
Set pCol = RetVal
If oFld2 Is Nothing Then
Do
pCol.Add .Bookmark, CStr(oFld.Value)
.MoveNext
Loop While Not .EOF
ElseIf oFld3 Is Nothing Then
Do
pCol.Add .Bookmark, CStr(oFld.Value) & "#" & CStr(oFld2.Value)
.MoveNext
Loop While Not .EOF
Else
Do
pCol.Add .Bookmark, CStr(oFld.Value) & "#" & CStr(oFld2.Value) & "#" & CStr(oFld3.Value)
.MoveNext
Loop While Not .EOF
End If
On Error GoTo 0
Else
If oFld2 Is Nothing Then
Do
RetVal.Add .Bookmark, CStr(oFld.Value)
.MoveNext
Loop While Not .EOF
ElseIf oFld3 Is Nothing Then
Do
RetVal.Add .Bookmark, CStr(oFld.Value) & "#" & CStr(oFld2.Value)
.MoveNext
Loop While Not .EOF
Else
Do
RetVal.Add .Bookmark, CStr(oFld.Value) & "#" & CStr(oFld2.Value) & "#" & CStr(oFld3.Value)
.MoveNext
Loop While Not .EOF
End If
End If
If Not IsEmpty(vBmk) Then
.Bookmark = vBmk
End If
End If
End With
Set InitIndexCollection = RetVal
End Function
然后你可以像这样用Bookmark
属性快速查找
Dim rsItems As Recordset
Dim cIndex As Collection
Set cIndex = InitIndexCollection(rsItems, "Code")
...
'--- loop on other rs'
Do While Not rs.EOF
...
rsItems.Bookmark = cIndex(rs!ItemCode.Value) '--- this is seek'
...
rs.MoveNext
Loop
我正在将一些旧的遗留访问代码转换为 SQL,用于我们的遗留程序,在该程序中我们根据数千条记录的数据创建报告。我们使用多个记录集来访问不同的 records/tables。以前(在访问中),我们使用 Recordset.Seek 函数在记录集中找到所需的记录。这样做可以让我们在几秒钟内获得我们想要的数据。
在使用 ADO 记录集而不是 DAO 将其转换为与 SQL 一起使用时,我发现大多数人建议简单地将记录集设置为等于新记录集的查询,该查询将 return想要的记录。到目前为止,这是执行此操作的最有效方法,但这仍然需要最多 2 分钟才能获得需要几秒钟才能访问的相同数据。
我看到 ADO Recordset 也有一个 .seek 函数,但我在尝试实现它以进行比较时遇到了问题 speed/accuracy。如果这是更好的方法,我如何 create/set 记录集的索引,以及如何知道索引的名称?
谢谢!
您只能将 Seek
用于来自 JET OLEDB 提供程序的服务器端记录集。您可以使用 rs.Supports(adSeek)
.
Seek
是否可用
我通常对客户端记录集所做的是使用如下函数构建内存中索引"by hand":
Public Function InitIndexCollection( _
rs As Recordset, _
sFld As String, _
Optional Fld2 As String, _
Optional Fld3 As String, _
Optional ByVal HasDuplicates As Boolean, _
Optional RetVal As Collection) As Collection
Const FUNC_NAME As String = "InitIndexCollection"
Dim oFld As ADODB.Field
Dim oFld2 As ADODB.Field
Dim oFld3 As ADODB.Field
Dim vBmk As Variant
Dim pCol As Collection '-- IVbCollection that doesn't raise duplicate error on Add
Set RetVal = New Collection
With rs
If .RecordCount > 0 Then
On Error Resume Next
vBmk = rs.Bookmark
On Error GoTo 0
.MoveFirst
Set oFld = .Fields(sFld)
If LenB(Fld2) <> 0 Then
Set oFld2 = .Fields(Fld2)
End If
If LenB(Fld3) <> 0 Then
Set oFld3 = .Fields(Fld3)
End If
If HasDuplicates Then
On Error Resume Next
Set pCol = RetVal
If oFld2 Is Nothing Then
Do
pCol.Add .Bookmark, CStr(oFld.Value)
.MoveNext
Loop While Not .EOF
ElseIf oFld3 Is Nothing Then
Do
pCol.Add .Bookmark, CStr(oFld.Value) & "#" & CStr(oFld2.Value)
.MoveNext
Loop While Not .EOF
Else
Do
pCol.Add .Bookmark, CStr(oFld.Value) & "#" & CStr(oFld2.Value) & "#" & CStr(oFld3.Value)
.MoveNext
Loop While Not .EOF
End If
On Error GoTo 0
Else
If oFld2 Is Nothing Then
Do
RetVal.Add .Bookmark, CStr(oFld.Value)
.MoveNext
Loop While Not .EOF
ElseIf oFld3 Is Nothing Then
Do
RetVal.Add .Bookmark, CStr(oFld.Value) & "#" & CStr(oFld2.Value)
.MoveNext
Loop While Not .EOF
Else
Do
RetVal.Add .Bookmark, CStr(oFld.Value) & "#" & CStr(oFld2.Value) & "#" & CStr(oFld3.Value)
.MoveNext
Loop While Not .EOF
End If
End If
If Not IsEmpty(vBmk) Then
.Bookmark = vBmk
End If
End If
End With
Set InitIndexCollection = RetVal
End Function
然后你可以像这样用Bookmark
属性快速查找
Dim rsItems As Recordset
Dim cIndex As Collection
Set cIndex = InitIndexCollection(rsItems, "Code")
...
'--- loop on other rs'
Do While Not rs.EOF
...
rsItems.Bookmark = cIndex(rs!ItemCode.Value) '--- this is seek'
...
rs.MoveNext
Loop