【问题标题】:DoCmd.RunSQL is resulting in Run-time error 2342 or Run-time error 3129DoCmd.RunSQL 导致运行时错误 2342 或运行时错误 3129
【发布时间】:2021-12-20 05:10:40
【问题描述】:

简而言之:

我在开发数据库方面做得很好,但我确实需要从 VBA 运行 SELECT 查询,因为我最终需要使用命名其中一个表的变量来运行它。

这是我的代码:

SqlStr = "SELECT tblFall2021.fldUserID, tblFall2021.fldDate, tblFall2021.fldTime, tblFall2021.fldUserName, " & _ 
" tblVolunteers.ID, tblVolunteers.fldPhone, tblVolunteers.fldEmail, tblVolunteers.[fldChurch/Parish], " & _
" tblVolunteers.fldGroup, tblVolunteers.[fldCouncil/Court] " & _ 
" FROM tblFall2021 INNER JOIN tblVolunteers ON tblFall2021.[fldUserID] = tblVolunteers.[ID] " & _ 
" WHERE (((tblFall2021.fldDate)='9/22/2021'));" 

' MsgBox SqlStr 
DoCmd.RunSQL SqlStr

按原样运行会得到运行时错误“2342”: RunSQL 操作需要一个由 SQL 语句组成的参数。

我尝试在前端和后端将 " 加倍,但 VBA 根本不喜欢这样;我认为它全部变成红色,因为它是一个坏字符串。

所以我将“”增加了三倍并运行它并得到:

运行时错误“3129”:无效的 SQL 语句;预期“删除”, 'INSERT'、'PROCEDURE'、'SELECT' 或 'UPDATE'。

上面显示的字符串的形成与 Microsoft 的示例完全匹配。但是在我寻求帮助的任何地方都告诉我 DoCmd.RunSQL 只会运行操作查询,而不是选择查询,尽管 Microsoft 另有说明:

一个字符串表达式,它是操作查询的有效 SQL 语句 或数据定义查询。它使用 INSERT INTO、DELETE、 选择...进入、更新、创建表、更改表、删除表、创建 INDEX 或 DROP INDEX 语句。如果需要,请包含 IN 子句 访问另一个数据库。

https://docs.microsoft.com/en-us/office/vba/api/access.docmd.runsql

我之前在这个网站上被告知 DoCmd.RunSQL 仅用于 SELECT 查询,不会执行操作查询。

(我也尝试在前后使用 Chr(34) 代替额外的引号,这也会产生运行时错误“3129”。)

上面的字符串有问题吗?我直接从有效查询的 SQL 视图中复制了它,并将其格式化以符合 Microsoft 的建议。

所以我完全没有想法。

提前致谢。

【问题讨论】:

  • 我之前在这个网站上被告知 DoCmd.RunSQL 仅用于 SELECT 查询,不会执行操作查询。 - 如果您再次发现,请离开评论中的链接,以便我们修复它。这是相反的方式。谢谢。

标签: sql vba ms-access


【解决方案1】:

您的 SQL 字符串看起来正确,但请参阅此处以确保:How to debug dynamic SQL in VBA

但是:DoCmd.RunSQL 真的只用于操作查询。

虽然已知 Microsoft 的文档有时不正确,但事实并非如此:SELECT...INTO 确实是一个操作查询,它​​会创建一个新表。

SELECT ... FROM ... 只返回数据。你想对结果数据做什么?

  • 要使用 VBA 处理它,请使用 DB.OpenRecordset
  • 要向用户显示数据,您需要一个已保存的查询(如果必须,您可以即时创建),您可以使用DoCmd.OpenQuery 打开该查询。

【讨论】:

    【解决方案2】:

    考虑操作或结果集查询的存储命名查询。在 MS Access 中,保存的查询比在代码(VBA、Python、Java 等)中构建的 SQL 语句更有效,因为 Access 查询引擎对保存的查询运行统计信息,并将保存最佳执行计划。

    您甚至可以使用QueryDefs 动态调整已保存的命名查询的 SQL,如下所示,这可能是您的预期目标,如

    需要使用命名其中一个表的变量来运行它

    因此,请考虑使用以下 SQL 在 Access 中创建命名查询对象。请注意使用表别名来减少冗长和修复日期逻辑,因为 Access 不会直接将日期/时间类型等同于日期字符串。

    SQL

    SELECT t.fldUserID
         , t.fldDate
         , t.fldTime
         , t.fldUserName
         , v.ID
         , v.fldPhone
         , v.fldEmail
         , v.[fldChurch/Parish]
         , v.fldGroup
         , v.[fldCouncil/Court] 
    FROM tblFall2021 t
    INNER JOIN tblVolunteers v
        ON t.[fldUserID] = v.[ID] 
    WHERE t.fldDate = CDate('9/22/2021');
    

    现在,如果您需要将tblFall2021 换成不同的表,由于使用表别名,您只需要这样做一次,并且可以使用 VBA。

    VBA

    Dim newTable As String
    Dim qDef As QueryDef
    
    newTable = "tblSpring2022"
    
    ' RETRIEVE SPECIFIC QUERYDEF
    Set qdef = CurrentDb.QueryDefs("mySavedNamedQuery")
    
    ' ADJUST SQL PROPERTY
    qdef.SQL = Replace(qdef.SQL, "tblFall2021", newTable)
    
    ' RELEASE QUERY TO SAVE CHANGES
    Set qdef = Nothing
    

    然后,在任何可以使用查询对象的地方使用调整后的查询:

    ' OPEN ADJUSTED QUERY OBJECT
    DoCmd.OpenQuery "mySavedNamedQuery"
    
    ' ASSIGN OPEN FORM OR REPORT TO ADJUSTED QUERY
    Forms!myForm.Form.RecordSource = "mySavedNamedQuery"
    Reports!myReport.Report.RecordSource = "mySavedNamedQuery"
    
    ' OPEN A RECORDSET OF QUERY, EVEN USE ABOVE QUERYDEF (BEFORE RELEASE)
    Set rst = CurrentDb.OpenRecordset("mySavedNamedQuery")
    Set rst = qdef.OpenRecordset()
    

    【讨论】:

    • 这需要我一点时间来吸收所有这些,但我认为 Parfait 的 cmets 解决了我的两个问题(并且会减少我启动的代码。并且只需要一个永久查询,也向善。谢谢大家!
    • 很高兴听到并乐于提供帮助!不要忘记 StackOverflow 的说法 thanks,它也可以确认解决方案。
    • 好的,我显然已经吸收了足够多的东西(就目前而言),因为它现在正在做我想要的! (下一步是创建要从查询中加载的表单或报告,但我认为我或多或少知道如何做到这一点。)我是新来的:StackOverflow 表示感谢的方式是什么。我当然想。谢谢。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2016-08-05
    • 2015-11-02
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-07-08
    相关资源
    最近更新 更多