Microsoft Access VBA编辑SQL查询

时间:2010-02-12 11:12:47

标签: ms-access vba access-vba

我有一个Access数据库,其中包含一个查询。我目前可以使用DoCmd.CopyObject通过VBA复制查询。但是,我需要能够单独编辑查询的每个实例中的SQL。然而,我所看到的所有例子都涉及记录集,这是我没有使用的。

有什么想法吗?

3 个答案:

答案 0 :(得分:2)

我一直这样做!我已经使用VBA来重写Access查询以及“通过”到MySQL数据库的查询。在VBA中重写查询取决于您想要获得的复杂程度。

我一直使用DAO这是旧技术(请参阅下面的评论以澄清DAO vs ADO),但在这种情况下它对我有用。您需要通过转到工具>在VBA中添加对DAO的引用。引用,然后添加“Microsoft DAO 3.6 Object Library。”

您可以编写一个如下所示的过程:

Sub RewriteQuerySQL(strQueryName As String, strParameter As String)
    Dim db As DAO.Database
    Dim qdf As DAO.QueryDef
    Set db = CurrentDb()
    Set qdf = db.QueryDefs(strQueryName)

    qdf.SQL = "SELECT [Table].Field1, [Table].Field2 " & vbCrLf & _
              "FROM [Table] " & vbCrLf & _
              "WHERE ([Table].Field1 = " & chr(34) & strParameter & chr(34) & ");"
End Sub

上面的代码将使用SQL查询中嵌入了strParameter的VBA代码中的查询SQL来更改您指定的查询的SQL。

这是另一种做法。这是我在销售报告应用程序中使用的代码,用于根据销售人员的编号重写查询:

Sub rewriteAccountsBySalesRepSortSQL(lngSalesRep As Long)
    Dim db As DAO.Database
    Dim qdf As DAO.QueryDef
    Dim strSQL As String
    Dim strOriginal As String
    Dim strReplacePart As String
    Dim strSQLReplace As String
    Dim lngLocSalesperson As Long
    Dim lngLocMyRoundUp As Long
    Dim lngLocParen As Long
    Dim lngLocEndParen As Long

    Set db = CurrentDb()
    Set qdf = db.QueryDefs("qryS Accounts by Sales Rep Sorted by Diff DESC")
    strSQL = qdf.SQL

    lngLocSalesperson = InStr(strSQL, "Salesperson1)=")
    lngLocEndParen = InStr(lngLocSalesperson + 14, strSQL, ")")
    strOriginal = Mid(strSQL, lngLocSalesperson, lngLocEndParen - lngLocSalesperson)
    'lngLocParen = InStrRev(strSQL, "(", lngLocSalesperson)

    strReplacePart = "Salesperson1)=" & lngSalesRep

    strSQLReplace = Replace(strSQL, strOriginal, strReplacePart)
    qdf.SQL = strSQLReplace
End Sub

代码不是写出整个查询,而是简单地找到当前的销售代表编号并用新编号替换它。我其实更喜欢后一种方法。后一种方法用于直接向MySQL发送查询,因此Access查询的语法可能略有不同。

答案 1 :(得分:2)

我不同意这里给出的所有答案,即使他们确实解决了问题。我不同意,因为我认为问题是基于不正确的假设 - 根本不需要重写SQL。

这个问题似乎假设必须保存Access中的查询。他们没有。您可以随时在代码中执行任意SQL字符串,或者(对于非DML SQL)作为表单或报表的记录源。 SQL字符串可以在运行时构建并在运行时根据需要进行分配 - 保存的QueryDef的唯一优势是,如果您需要在多个位置使用它。

保存的QueryDef与服务器数据库中的VIEW基本相同。

如果QueryDef有参数,它相当于一个简单的STORED PROCEDURE(即缺少代码的那些,如IF / THEN或CASE SELECT分支)。

如果要在服务器数据库上将SQL实现为VIEW,请将其另存为Access中的QueryDef。如果您在服务器数据库中将其作为SPROC执行,请将其实现为已保存的参数查询。

但首先,确定是否需要保存它。

值得一提的是,自1996年以来,我一直在Access中进行专业编程,而且我通常不会保存大量查询,特别是在查询中不保存条件。条件特定于运行时上下文,应在运行时提供,而不是保存在QueryDef中。我将保存的QueryDefs用于我需要重用的复杂SQL,或者用于定义在应用程序中多个位置使用的“视图”(特别是那些具有复杂连接的视图)。

原始问题并未确定需要更改标准的背景,因此建议采用最佳方法是不可能的。在这种情况下,我会因为它提出一个特定的解决方案并询问如何实施它而不是描述问题并询问可行解决方案的范围而错误地排除正确讨论的问题。为了完成后者,我们需要了解上下文(是SQL DML还是SELECT?它是在代码中使用还是作为表单或报表的记录源?等等),但这里完全没有,因此永远不会提供全方位的解决方案。

答案 2 :(得分:1)

问题在于您想要编辑哪种查询,但是说它是一个不需要任何动态参数的选择查询。

然后,使用CopyObject方法,像您一样制作查询的副本。使用Catalog对象(您需要引用ADO Ext)。然后,您可以更改副本的SQL,如下所示。根据您的查询,它可能是视图或过程,但选择查询应列为视图。

Dim catDB As ADOX.Catalog
Dim cmd As ADODB.Command
Dim sQueryName As String
Dim sSQL As String

Set cn = CurrentProject.Connection
Set catDB = New ADOX.Catalog

catDB.ActiveConnection = cn
DoCmd.CopyObject , "Query1_c", acQuery, "Query1"
sQueryName = "Query1_c"
sSQL = "SELECT a,b,c FROM Table1"

Set cmd = New ADODB.Command
Set cmd = catDB.Views(sQueryName).Command
cmd.CommandText = sSQL
Set catDB.Views(sQueryName).Command = cmd

Set catDB = Nothing
cn.Close