将完整的 ADO 记录集插入现有的 ACCESS 表而不使用循环
Posted
技术标签:
【中文标题】将完整的 ADO 记录集插入现有的 ACCESS 表而不使用循环【英文标题】:insert full ADO Recordset into existing ACCESS table WITHOUT LOOP 【发布时间】:2015-12-25 14:44:20 【问题描述】:我的 VBA 模块中有一个填充的 ADO 记录集。我在 ACCESS 中也有一个与记录集结构完全相同的表。
现在我使用循环(这很好)遍历每个数据集记录来填充表格。
我想知道的是:有没有办法将整个记录集插入到访问表中? (更重要的是:这会明显更快)
【问题讨论】:
【参考方案1】:这是一个基本示例(在本例中从 excel 运行),说明使用断开连接的记录集添加记录。
Sub Tester()
Dim con As ADODB.Connection, rs As ADODB.Recordset
Dim i As Long
Set con = getConn()
Set rs = New ADODB.Recordset
rs.CursorLocation = adUseClient '<<<< important!
'get an empty recordset to add new records to
rs.Open "select * from Table1 where false", con, _
adOpenDynamic, adLockBatchOptimistic
'disconnect the recordset and close the connection
Set rs.ActiveConnection = Nothing
con.Close
Set con = Nothing
'add some new records to our test recordset
For i = 1 To 100
rs.AddNew
rs("UserName") = "Newuser_" & i
Next i
'reconnect to update
Set con = getConn()
Set rs.ActiveConnection = con
rs.UpdateBatch '<<< transfer to DB happens here: no loop!
rs.Close
'requery to demonstrate insert was successful
rs.Open "select * from Table1", con, _
adOpenDynamic, adLockBatchOptimistic
Do While Not rs.EOF
Debug.Print rs("ID").Value, rs("UserName").Value
rs.MoveNext
Loop
rs.Close
con.Close
End Sub
Function getConn() As ADODB.Connection
Dim rv As New ADODB.Connection
Dim strConn As String
strConn = "Provider=Microsoft.ACE.OLEDB.12.0;" _
& "Data Source = " & ThisWorkbook.Path & "\Test.accdb"
rv.Open strConn
Set getConn = rv
End Function
【讨论】:
谢谢,我用了类似的东西。问题是如何避免必须使用循环,而只需将整个记录集转储到表中,就像您可以在两个访问表之间执行的操作一样 (SELECT * INTO SomeTable FROM SomewhereElse) 但仍然很有用! 我唯一的循环是加载测试记录集并在更新后显示结果。数据加载全部发生在单个UpdateBatch
行中。你指的是什么循环?
糟糕,我意识到我错过了最重要的部分。但我现在明白了。这就是我希望找到的。非常有帮助,感谢您的澄清
@tim 很奇怪,我认为您的回答实际上并没有回答这个问题。当然,这是关于建立一个记录集,然后将其放回不同的或任何!桌子。 Parfait 的回答概述了一种方法,您对此有何看法。你的回答把它放回了它来自的表中(这将涵盖 99.9% 的场景,包括 OP 的场景!)
@HarveyFrench - OP 的问题开始于“我有一个已填充的 ADO 记录集”,所以在我看来问题不是关于 填充 记录集,而是关于如何将那些记录从 OP 已经拥有的记录集中插入到表中而不循环。我发布的代码是使用UpdateBatch
方法执行此操作的示例。由于 OP 没有发布任何与创建他们的记录集相关的代码,而且我感到很懒惰,我使用从目标表中选择的“无记录”创建了我的 example 记录集,以确保字段匹配正是。【参考方案2】:
VBA 记录集实际上存在于运行时调用的内存中,直到它们包含在保存到硬盘上的实际物理格式(即 csv、txt、xlsx、xml、数据库临时表)中。这类似于 R 或 Python pandas、SAS 数据集、php 数组和其他数据结构中的数据帧。
考虑使用CopyFromRecordset 方法将您的ADO 以这种格式导出到Excel 电子表格中,以保存为csv、txt、xlsx 或xml。或者,您可以使用Save 方法将记录集保存为持久格式类型,例如 xml。
然后,使用其自动数据迁移功能将结果文件附加到 MS Access 表中:
对于电子表格:DoCmd.TransferSpreadsheet
对于 txt、csv 或其他分隔文件:DoCmd.TransferText
对于 xml 文件:Application.ImportXML
对于本地或 ODBC/OLEDB 链接数据库表:INSERT INTO
附加 SQL 查询
【讨论】:
ADO 到 Excel 到 Access。听起来它会比循环 INSERT 语句更快。遗憾的是,您不能使用 SELECT 语句从记录集(或者可能是数组......嗯。值......【参考方案3】:没有。没有反向等价物 - 可能是 SetRows
- 方法 GetRows
。
【讨论】:
【参考方案4】:要使用 SQL 语句完成此操作,请使用 SELECT/INSERT... IN [Designate DB A;记录张贴到] 或 FROM... IN [指定 DB B;记录原始出处]
您只能在单个查询中使用一次 IN 语句。因此,您使用 ADODB 连接来创建其他连接以确定其他源连接。
Function example()
Dim dB_External As String
Dim db_Local As String
Dim cnLocal As ADODB.Connection
Dim cnExternal As ADODB.Connection
Set cnLocal = CurrentProject.Connection
Set cnExternal = New ADODB.Connection
cnExternal .Open "Provider=Microsoft.ACE.OLEDB.12.0;Data Source=C:\Users\\...accdb;Persist Security Info=False;"
dB_External = "C:\Users\\...accdb"
db_LOCAL = "C:\Users\\...accdb"
Example A:
strSQL = "INSERT INTO *Local table to receive records* (Column Designations)"
strSQL = strSQL & " SELECT ( *Corresponding records from external table* )"
strSQL = strSQL & " FROM *External table name* IN '" & dB_External & "'"
cnLocal.Execute (strSQL)
如果我从单个外部表中选择,我使用上面的代码和本地 ADODB 连接。
Example B:
strSQL = "INSERT INTO *Local table to receive records* (Column Designations) IN '" & dblocal & "'"
strSQL = strSQL & " ( *Corresponding records from external table* )"
strSQL = strSQL & " FROM *External table name*
cnExternal.Execute (strSQL)
我使用上面的代码使用外部 ADODB 连接,如果我选择涉及连接外部数据库中的多个表。
【讨论】:
以上是关于将完整的 ADO 记录集插入现有的 ACCESS 表而不使用循环的主要内容,如果未能解决你的问题,请参考以下文章
如何从 ADO 记录集字段将图片加载到 MS-Access Image 控件中?
MS Access - ADO 记录集,使用 SQL 语句检索数据和建表