如何使用 VBA 将“整个”DAO 记录集插入到表中

Posted

技术标签:

【中文标题】如何使用 VBA 将“整个”DAO 记录集插入到表中【英文标题】:How to insert "Entire" DAO recordset into a table with VBA 【发布时间】:2011-10-14 03:43:15 【问题描述】:

我有一个创建良好的 DAO 记录集,我可以将记录从集合传输到表,这是逐行完成的,效果很好,但我一次传输大量数据,所以这可能需要很长的时间一行一行。

有没有办法一次性传输整个记录集,而不是逐行传输

当前使用的代码见下文-

Dim SendE1 As DAO.Recordset

Set SendE1 = CurrentDb.OpenRecordset("SELECT TBL_ImportTable.* FROM TBL_ImportTable", dbOpenDynaset)

SendE1.MoveLast

Do Until SendE1.EOF

sqlinsert = "INSERT INTO TBL_E1Jobs (StartDate, StartTime, EndDate, EndTime, Location, UserID, WorkStationID, DocumentNumber, E1Shift, OperSeq, Facility, AdjustedforShifts, WeekNum)" & _
" VALUES ('" & SendE1("StartDate") & "', '" & SendE1("StartTime") & "', '" & SendE1("EndDate") & "', '" & SendE1("EndTime") & "', '" & SendE1("Location") & "', '" & SendE1("UserID") & "', '" & SendE1("WorkstationID") & "', '" & SendE1("DocumentNumber") & "', '" & SendE1("E1Shift") & "', '" & SendE1("OperSeq") & "', '" & SendE1("Facility") & "', '" & SendE1("AdjustedforShifts") & "', '" & SendE1("WeekNum") & "') "

DoCmd.RunSQL (sqlinsert)

SendE1.MoveNext

Loop


SendE1.Close
Set SendE1 = Nothing

【问题讨论】:

【参考方案1】:

@cularis 是正确的。执行此操作的正确方法是在 SQL 查询中。在阅读了您的 cmets 对他的回答后,您可以采取一些步骤来避免清除未复制的数据:

Dim db As DAO.Database, RecCount As Long

'Get the total number of records in your import table to compare later
RecCount = DCount("*", "TBL_ImportTable")

'This line is IMPORTANT! each time you call CurrentDb a new db object is returned
'  that would cause problems for us later 
Set db = CurrentDb

'Add the records, being sure to use our db object, not CurrentDb
db.Execute "INSERT INTO TBL_E1Jobs (StartDate, StartTime, ..., WeekNum) " & _
           "SELECT StartDate, StartTime, ..., WeekNum " & _
           "FROM TBL_ImportTable", dbFailOnError

'db.RecordsAffected now contains the number of records that were inserted above
'  since CurrentDb returns a new db object, CurrentDb.RecordsAffected always = 0
If RecCount = db.RecordsAffected Then
    db.Execute "DELETE * FROM TBL_ImportTable", dbFailOnError
End If

请注意,如果您对链接的 ODBC 表运行这些查询,则需要包含dbSeeChanges 选项(即dbFailOnError + dbSeeChanges)。

【讨论】:

事务会确保db.Execute INSERT 在继续之前完成吗?我认为可能,但我不确定。 我不知道。我从来没有亲身经历过OP似乎在查询完成之前代码移动的问题。但也许我从来没有在查询完全完成如此关键的慢速网络上真正测试过。【参考方案2】:

不是 DAO,而是 SQL 解决方案,可以满足您的需求:

INSERT INTO TBL_E1Jobs  (StartDate, StartTime, EndDate ...) 
SELECT StartDate, StartTime, EndDate ... FROM TBL_ImportTable

INSERT INTO ... SELECT MSDN

【讨论】:

我最初确实将其作为解决方案,但是我找不到确保 SQL 解决方案在开始下一个 SQL 代码部分之前完成的方法。 DoCmd.RunSQL 仅应在 SQL 命令完成/因错误中止时返回。 我有一个插入 sql 命令,然后是一个删除 sql 命令。因此,insert 会将数据从 IMPORT 传输到 E1JOBS。然后删除将擦除导入表...我注意到如果插入功能需要很长时间(后端位于联网服务器而不是本地桌面,因此网络拥塞发挥作用)然后删除 sql 会踢在它完成并删除表之前。剩下一半的数据没有传输。 哇,这不应该发生。我想不出导致这种情况的原因,也许DWF 知道;),但是如果所有行都在新表中,您可以在INSERT ... SELECT 之后进行某种检查。 同意它不应该发生,它让我困惑了一段时间。这就是我选择 DAO 的原因,但我知道的唯一传输方法是逐行传输。这消除了丢失数据的风险,但需要永远。支票可能是值得一看的......我会考虑一下

以上是关于如何使用 VBA 将“整个”DAO 记录集插入到表中的主要内容,如果未能解决你的问题,请参考以下文章

大型记录集 (VBA) 的 MS Access 插入慢

记录集到表?

将完整的 ADO 记录集插入现有的 ACCESS 表而不使用循环

使用事务的 DAO 记录集批量更新(excel)

将 DAO 记录集转换为断开连接的 ADO 记录集 dbDecimal 问题

将小数传递给 vba 的问题