【问题标题】:Is it possible to run a make table query using a recordset as the source in MS Access (VBA)?是否可以使用记录集作为 MS Access (VBA) 中的源来运行生成表查询?
【发布时间】:2019-07-01 17:59:49
【问题描述】:

我有一个 MS Access 数据库,我正在尝试对名为 tblPrevious 的表进行重复数据删除。我创建了一个仅从表中选择不同值的记录集,我想使用该记录集覆盖原始表。我无法使用普通的生成表查询,因为我不能使用tblPrevious 作为目标表和源表。所以我的计划是通过vba创建一个记录集,然后删除原表,然后使用记录集填充一个与原tblPrevious同名的新表。我的另一个选择是创建一个名为tblPrevious2 的新表,然后删除tblPrevious,然后将tblPrevious2 重命名为tblPrevious。这对我来说似乎太乱了。以下是我尝试的 vba,但收到一条失败消息,提示“运行时错误 3078,Microsoft Access 数据库引擎找不到输入表或查询“rst”。提前感谢您的帮助!

Sub RemovePreviousDupes()


Dim rst As Recordset Set rst = CurrentDb.OpenRecordset(Name:="DeDupetblPreviousExport", Type:=RecordsetTypeEnum.dbOpenDynaset)

strSQL = "SELECT rst.* INTO DELETETABLE FROM rst;"

DoCmd.RunSQL (strSQL)


End Sub

DeDupetblPreviousExport 添加了 SQL。另请注意,在上面的代码中,我只是试图将记录集写入一个新表,如果我要让它工作,我会尝试删除tblPrevious,上面的最后一行将写入tblPrevious,而不是DELETETABLE

SELECT DISTINCT tblPreviousExport.[Month Reported], tblPreviousExport.[Employee SSN],   
                tblPreviousExport.[Employee First Name], tblPreviousExport.[Employee Last Name], 
                tblPreviousExport.Pool, tblPreviousExport.OpCo, tblPreviousExport.Paygroup, 
                tblPreviousExport.[Effective Date], tblPreviousExport.[Medical Plan], 
                tblPreviousExport.[Coverage Level], tblPreviousExport.Type, 
                tblPreviousExport.[Tier Change Effective Date], tblPreviousExport.[Num Eligible Months], 
                tblPreviousExport.[Employee Ongoing Contribution], 
                tblPreviousExport.[Full Employer Contribution], 
                tblPreviousExport.[Prorated Employer Contribution],
                tblPreviousExport.[ER Contribution Already Received], 
                tblPreviousExport.[Total Contribution], tblPreviousExport.[Max Contribution]
FROM tblPreviousExport;

【问题讨论】:

  • 为什么不删除原始表中的副本?请显示DeDupetblPreviousExport的查询来源。
  • 感谢您的快速回复!不确定删除原始表中重复数据的最佳方法。我正在尝试这个,因为它似乎是我知道如何做的最简单的方法。如果您有更快/更简单的方法,那么我很想尝试一下。

标签: sql vba ms-access


【解决方案1】:

不。您不能以记录集作为源(或者实际上是任何查询)运行操作查询。

改为使用记录集的源作为查询的源。

如果要将记录集写入表,也可以考虑通过VBA创建表,然后使用循环将记录写入表。

【讨论】:

  • 所以如果我要尝试这种方法,我需要创建一个新表,然后删除原始表,然后用原始表的名称重命名新表。您知道对表格进行重复数据删除的更好/更清洁的方法吗?我正在为此苦苦挣扎,看起来它应该相当简单,无需创建额外的表等。
  • 如果您有一个主键,您应该能够在单个操作查询中进行重复数据删除。如果没有,请添加 PK。
  • 我原本没有PK,但我加了一个。我知道我过去做过,但我不记得是怎么做的(离开 Access 有一段时间了)。你知道 SQL 会是什么样子吗?
  • 一般:DELETE * FROM Table t1 WHERE EXISTS(SELECT 1 FROM Table t2 WHERE t1.PK <> t2.PK AND t1.Col1 = t2.Col1 AND t1.Col2 = t2.Col2 etc)
【解决方案2】:

假设您的表维护一个唯一的主键,例如自动编号 id,请考虑使用纯 SQL 对原始表进行重复数据删除,并避免使用临时表或记录集。具体来说,使用IN 子句运行DELETE 以保持与所有匹配列相对应的最小id

DELETE FROM tblPreviousExport main
WHERE id IN 
  (SELECT sub.id
   FROM tblPreviousExport sub
   WHERE sub.id > main.id
     AND sub.[Month Reported] = main.[Month Reported]
     AND sub.[Employee SSN] = main.[Employee SSN]
     AND sub.[Employee First Name] = main.[Employee First Name]
     AND sub.[Employee Last Name] = main.[Employee Last Name]
     AND sub.Pool = main.Pool 
     AND sub.OpCo = main.OpCo 
     AND sub.Paygroup = main.Paygroup 
     AND sub.Pool = main.Pool
     AND sub.[Effective Date] = main.[Effective Date] 
     AND sub.[Medical Plan] = main.[Medical Plan] 
     AND sub.[Coverage Level] = main.[Coverage Level]
     AND sub.Type = main.Type 
     AND sub.[Tier Change Effective Date] = main.[Tier Change Effective Date]
     AND sub.[Num Eligible Months] = main.[Num Eligible Months]
     AND sub.[Employee Ongoing Contribution] = main.[Employee Ongoing Contribution]
     AND sub.[Full Employer Contribution] = main.[Full Employer Contribution]
     AND sub.[Prorated Employer Contribution] = main.[Prorated Employer Contribution]
     AND sub.[ER Contribution Already Received] = main.[ER Contribution Already Received]
     AND sub.[Total Contribution] = main.[Total Contribution]
     AND sub.[Max Contribution] = main.[Max Contribution])

或使用EXISTS 子句:

DELETE FROM tblPreviousExport main
WHERE id EXISTS
  (SELECT 1
   FROM tblPreviousExport sub
   WHERE sub.id > main.id
     AND sub.[Month Reported] = main.[Month Reported]
     AND sub.[Employee SSN] = main.[Employee SSN]
     AND sub.[Employee First Name] = main.[Employee First Name]
     AND sub.[Employee Last Name] = main.[Employee Last Name]
     AND sub.Pool = main.Pool 
     AND sub.OpCo = main.OpCo 
     AND sub.Paygroup = main.Paygroup 
     AND sub.Pool = main.Pool
     AND sub.[Effective Date] = main.[Effective Date] 
     AND sub.[Medical Plan] = main.[Medical Plan] 
     AND sub.[Coverage Level] = main.[Coverage Level]
     AND sub.Type = main.Type 
     AND sub.[Tier Change Effective Date] = main.[Tier Change Effective Date]
     AND sub.[Num Eligible Months] = main.[Num Eligible Months]
     AND sub.[Employee Ongoing Contribution] = main.[Employee Ongoing Contribution]
     AND sub.[Full Employer Contribution] = main.[Full Employer Contribution]
     AND sub.[Prorated Employer Contribution] = main.[Prorated Employer Contribution]
     AND sub.[ER Contribution Already Received] = main.[ER Contribution Already Received]
     AND sub.[Total Contribution] = main.[Total Contribution]
     AND sub.[Max Contribution] = main.[Max Contribution])

【讨论】:

    【解决方案3】:

    当您说: 我的另一个选择是创建一个名为 tblPrevious2 的新表,然后删除 tblPrevious,然后将 tblPrevious2 重命名为 tblPrevious

    取而代之的是: 创建一个名为 tblPrevious2 的新表,然后通过简单的 Delete Query 删除 tblPrevious 的记录(不是表本身),然后将 tblPrevious2 记录附加到 tblPrevious

    【讨论】:

      【解决方案4】:

      感谢大家的回复,感谢您愿意提供帮助。我最终做的是我最初认为会是一个混乱的方式,但最终要容易得多。我运行了一个生成表查询,只选择不同的记录并将新表命名为 tblPrevious2。然后我只运行DoCmd.Rename "tblPrevious", acTable, "tblPrevious2",它只是用新表替换了旧表。它比我预期的要干净得多,而且效果很好。

      【讨论】:

        猜你喜欢
        • 2011-01-06
        • 1970-01-01
        • 1970-01-01
        • 2021-09-30
        • 1970-01-01
        • 1970-01-01
        • 2010-11-19
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多