如何在 Microsoft Access 中通过 VBA 设置 INSERT SQL 查询的参数值?

Posted

技术标签:

【中文标题】如何在 Microsoft Access 中通过 VBA 设置 INSERT SQL 查询的参数值?【英文标题】:How can one set parameter values of an INSERT SQL query through VBA in Microsoft Access? 【发布时间】:2012-08-04 18:01:39 【问题描述】:

我是 Access 新手,我来自 C#、SQL Server 和 .Net。我遇到了一个项目,我必须完成一些部分。

场景可以描述为:

    带有子表单的 Access 表单 Access 查询是上述子表单的数据源,有两个参数,显示为:Parametername1 String(255),Parametername2 String(255)。 VBA 代码模块

我的计划是在我的 VBA 代码模块的过程中设置上述查询参数的值。我相信这应该刷新我的子表单,因为查询是子表单的数据源。

问题是我不知道如何实施这个计划。

我想使用查询,因为我不想用内联 SQL 搞乱我的 VBA 代码。

我正在使用 Access 2010。

【问题讨论】:

VBA 模块中的内联 SQL 是一个坏主意,不仅出于可读性目的,而且因为它可能引发意外错误并造成 security threat。 【参考方案1】:

我正好有这个问题,我想使用相同的“存储”更新查询,但从两种不同的形式执行它,所以想在运行时将参数传递给查询。这是我(在另一个论坛中)发现的,完全符合我的要求:

With CurrentDb.QueryDefs("qry_YourQuery")
   .Parameters("yourParam") = yourVBAvar
   .Execute
End With

【讨论】:

“qry_YourQuery”是什么样的?你只是把? 放在参数值应该放的地方吗? 你有链接到你找到这个sn-p的论坛吗?我搜索了,但我只能找到对这篇文章的引用。 对于那些想知道的人。 “qry_YourQyery”是您在访问数据库中的查询列表中保存的查询的名称,例如 qryUpdateSalary。 “yourParam”是您在查询中的参数名称,即更新 tblSalary 设置 Salary = 工资*工作小时,其中 PersonId = [人]。在这种情况下,参数是人,所以上面的例子看起来像code With CurrentDb.QueryDefs("qryUpdateSalary") .Parameters("person") = personID 'this variable comes from another step in the VBA code .Execute End With 【参考方案2】:

子表单的全部意义在于它由记录源以及链接子字段和主字段控制。假设表单是公司,子表单是员工,子表单的记录源可能是:

SELECT EmployeeID, CompanyID, Position, Etc FROM Employees

链接子字段和主字段将为 CompanyID。当您在主表单中移动时,只会显示与当前公司相关的那些记录。假设您只想显示那些技术职位的员工,您可以在运行时更改记录源:

SELECT EmployeeID, CompanyID, Position, Etc FROM Employees
WHERE Position = "Technical"

或者,如果这始终是表单上的过滤器,请在主表单中添加一个组合框,并将其用作第二个链接主字段,这样您就有了:

Link Master Fields:  CompanyID; cboPosition
Link Child Fields :  CompanyID; Position

最后,您可以简单地从主窗体中设置过滤器属性:

Me.Employees_subform.Form.Filter = "Position=""Tecnical"""
Me.Employees_subform.Form.FilterOn = True

如果这不是您的想法,请在您的问题中添加一些注释。

编辑

您可以通过引用表单上的控件来为查询提供参数:

SELECT EmployeeID, CompanyID, Position, Etc FROM Employees
WHERE Position = Forms!MyMainForm!cboPosition

您可以完全更改查询的 SQL,并且可以使用 ADO,但是,更改 SQL 类似于设置记录源,因为 SQL 是在代码中更改的,并且使用 ADO 通常不是表单的最佳选择。

你不能做的是改变一个参数并让它“粘”在一个表单或子表单上。

例如:

DoCmd.SetParameter "@SomeID", "1"
' This works
DoCmd.OpenQuery ("Queryx")

' This will give a prompt for @SomeID and then run
Me.SomeSubform.Form.RecordSource = "Queryx"

【讨论】:

Remou 谢谢。这肯定会有所帮助。但我不想使用过滤器。我已经有一个查询,它是子表单的记录源。我需要知道是否有任何方法可以更改/设置 VBA 代码中的查询参数。我正在寻找在 SQL 服务器中使用存储过程和在.net 中使用 SqlCommand (System.data.sqlclient) 类的解决方案。我什至不知道这是否可能。否则我只会将我的 sql 嵌入到我的 VBA 代码中,并使用 SQL stateemnt 作为我的记录/数据源并继续生活。访问不同! 访问是不同的,主要区别在于你可以在没有任何代码的情况下做很多事情,这是人们经常忘记的。在这种情况下,查询的参数应该来自表单,我指出了可能发生这种情况的方式。我错过了其他选项,我会添加它们。 再次感谢 Remou...我认为我们已经接近解决方案了。唯一的事情是我不希望应用程序提示查询中定义的参数。我想在我的 VBA 代码中设置参数的值....以你的例子 - where position = "Technical",我想在我的 VBA 代码中提供 "Technical" 的值 也许您想重新阅读我的回答?我说你不能在你设定的范围内这样做。如果您想提供“技术”,请将其写入控件并在查询中引用该控件,它可以是隐藏控件。 “技术”从何而来?如果用户正在提供它,那么您已经有了一个控件。 嗨 Remou 我认为我无法正确解释这个问题。我们已经偏离正题了。完全是我的错。查询的值将来自窗体上的控件。我需要的是一种避免将 SQL 语句嵌入到我正在编写的 VBA 代码中的方法。我想在存储过程 sql 中使用存储过程参数的行,如下所示选择 where 。我想将控件的值传递给查询并在查询中将其作为 prmcontrol1value 引用。谢谢【参考方案3】:

您可以创建一个函数并在表单的记录源查询中使用该函数(而不是常规参数)。

Public Function PositionParam(Optional ByVal P1 As Variant) As Variant
    Static varP As Variant

    If Not IsMissing(P1) Then
        If IsNull(P1) Then
            varP = Null
        Else
            varP = CStr(P1)
        End If
    ElseIf VarType(varP) = vbEmpty Then
        varP = Null
    End If
    PositionParam = varP
End Function

记录来源查询:

SELECT y.id_fld, y.another_fld, y.position_fld
FROM YourTable AS y
WHERE
       y.position_fld = PositionParam()
    OR PositionParam() Is Null
ORDER BY y.id_fld, y.another_fld;

稍后当您想在子表单中显示一组不同的行时,更改分配给子表单PositionParam()Requery 的值。

PositionParam "technician"
Forms("YourForm").Requery

【讨论】:

这可行。对我来说,我想我更愿意按照 Remou 的建议从表单中获取查询参数。但是,既然您似乎不想那样做,这是另一种方式。【参考方案4】:

子表单绑定到一个查询,该查询根本不应该有任何参数。

您当然可以将子表单的 SQL 存储在查询中,这样就消除了内联 sql,但是转而编写 WHACKS 代码来解决这个问题完全没有意义,不是吗?

如前所述,子表单重新编码的过滤和显示是自动的,如果您从控件设置子表单的主链接和子设置,则无需代码即可发生。您可能在这里不需要任何代码。

但是,如果出于某种真正原因您需要编写代码或想要更多的计费时间,那么您可以使用此代码:

Dim strSql     As String

strSql = Split(CurrentDb.QueryDefs("name of query").SQL, ";")(0)

strSql = strSql & "where Field1 = " & "'your p1 value'" & _
                  " and Field2 = " & "' your p2 value'"

Me.custChild.Form.RecordSource = strSql

因此您不需要在 sql 中使用任何参数,而只需使用子表单所基于的 CURRENT 和 SAME 查询。此外,如果您添加参数,那么您将在查询中对 2 个值进行硬编码,然后该查询不能用于其他代码和任务,除非您提供 2 个 SAME 硬编码参数(因此,在其他地方使用该查询时,这几乎没有灵活性有不同的选择)。

因此,将参数排除在查询之外,并保留相同的金钱和时间以及计费时间。

按照上述方法拉取查询 SQL 并将条件添加到 SQL 是一件简单的事情。但是,如果您希望将数据插入子表单,则可以直接使用子表单数据源和 reocrdset。例如:

  Dim rst     As DAO.Recordset

  Set rst = Me.custChild.Form.RecordsetClone

  rst.AddNew
  rst!SomeField = "some valjue"
  rst!SomeField2 = "some value"
  rst.Update

  Me.custChild.Requery

【讨论】:

以上是关于如何在 Microsoft Access 中通过 VBA 设置 INSERT SQL 查询的参数值?的主要内容,如果未能解决你的问题,请参考以下文章

如何在 MS Access 2007 或 MS SQL Server 2005 中通过 SQL 将字段转换为行

在 Access 中通过 VBA 存储集合

在 Access 中通过 VBA 传输表时出错

如何在 C# 中通过 lpEnvironment 调用 CreateProcess()

如何在 Azure 流分析中通过 IotHub.ConnectionDeviceId 对延迟函数进行分区?

ACCESS中通过一个字段更新另一个字段