当前位置: 首页 > 面试题库 >

如何在Microsoft Access中的不同上下文中在VBA中使用参数?

孟璞
2023-03-14
问题内容

我从bobby-tables.com之类的资源中读到了很多有关SQL注入和使用参数的信息。但是,我正在Access中使用一个复杂的应用程序,该应用程序具有很多动态SQL,并且在各种地方都有字符串连接。

我想更改以下内容并添加参数,以避免错误并允许我使用单引号处理名称,例如Jack O’Connel。

它用:

  • DoCmd.RunSQL 执行SQL命令
  • DAO记录集
  • ADODB记录集
  • 形式和报告,使用DoCmd.OpenForm和打开,并DoCmd.OpenReportWhereCondition参数中使用字符串连接
  • DLookUp这样的域聚合使用字符串连接

查询的结构大致如下:

DoCmd.RunSQL "INSERT INTO Table1(Field1) SELECT Field1 FROM Table2 WHERE ID = " & Me.SomeTextbox

在这些不同类型的查询中使用参数时,我有哪些选择?

此问题旨在作为一种资源,因为 经常在各种帖子中 使用参数 注释


问题答案:

有很多方法可以在查询中使用参数。我将尝试为其中的大多数示例以及适用的示例提供示例。

首先,我们将讨论Access独有的解决方案,例如表单,报表和域聚合。然后,我们将讨论DAO和ADO。

在Access中,您可以直接在SQL代码中使用表单和报表上控件的当前值。这限制了对参数的需求。

您可以通过以下方式引用控件:

Forms!MyForm!MyTextbox 用于对表单进行简单控制

Forms!MyForm!MySubform.Form!MyTextbox 用于子窗体上的控件

Reports!MyReport!MyTextbox 用于控制报告

实施示例:

DoCmd.RunSQL "INSERT INTO Table1(Field1) SELECT Forms!MyForm!MyTextbox" 'Inserts a single value
DoCmd.RunSQL "INSERT INTO Table1(Field1) SELECT Field1 FROM Table2 WHERE ID = Forms!MyForm!MyTextbox" 'Inserts from a different table

这可用于以下用途:

使用时DoCmd.RunSQL,常规查询(在GUI中),表单和报告记录源,表单和报告过滤器,域聚合DoCmd.OpenForm以及DoCmd.OpenReport

不适 用于以下用途:

使用DAO或ADODB执行查询时(例如,打开记录集CurrentDb.Execute

使用TempVars作为参数

Access中的TempVar是全局可用的变量,可以在VBA中或使用宏进行设置。它们可以重用于多个查询。

实施示例:

TempVars!MyTempVar = Me.MyTextbox.Value 'Note: .Value is required
DoCmd.RunSQL "INSERT INTO Table1(Field1) SELECT Field1 FROM Table2 WHERE ID = TempVars!MyTempVar"
TempVars.Remove "MyTempVar" 'Unset TempVar when you're done using it

TempVars的可用性与表单和报表中的值相同:不适用于ADO和DAO,可用于其他用途。

我建议使用TempVars在打开窗体或报告控件名称时使用参数,因为如果打开它的对象关闭,则TempVars仍然可用。我建议为每个表单或报表使用唯一的TempVar名称,以避免在刷新表单或报表时出现怪异现象。

使用自定义函数(UDF)作为参数

就像TempVars一样,您可以使用自定义函数和静态变量来存储和检索值。

实施示例:

Option Compare Database
Option Explicit

Private ThisDate As Date


Public Function GetThisDate() As Date
    If ThisDate = #12:00:00 AM# Then
        ' Set default value.
        ThisDate = Date
    End If 
    GetThisDate = ThisDate
End Function


Public Function SetThisDate(ByVal NewDate As Date) As Date
    ThisDate = NewDate
    SetThisDate = ThisDate
End Function

接着:

SetThisDate SomeDateValue ' Will store SomeDateValue in ThisDate.
DoCmd.RunSQL "INSERT INTO Table1(Field1) SELECT Field1 FROM Table2 WHERE [SomeDateField] = GetThisDate()"

同样,可以为设置和获取私有静态变量的值创建带有 可选 参数的 单个 函数: __

Public Function ThisValue(Optional ByVal Value As Variant) As Variant
    Static CurrentValue As Variant
    ' Define default return value.
    Const DefaultValue  As Variant = Null

    If Not IsMissing(Value) Then
        ' Set value.
        CurrentValue = Value
    ElseIf IsEmpty(CurrentValue) Then
        ' Set default value
        CurrentValue = DefaultValue
    End If
    ' Return value.
    ThisValue = CurrentValue
End Function

设置值:

ThisValue "Some text value"

要获取值:

CurrentValue = ThisValue

在查询中:

ThisValue "SomeText"  ' Set value to filter on.
DoCmd.RunSQL "INSERT INTO Table1(Field1) SELECT Field1 FROM Table2 WHERE [SomeField] = ThisValue()"

使用DoCmd.SetParameter

的用途DoCmd.SetParameter相当有限,因此我将作简要介绍。它允许您设置使用的参数DoCmd.OpenFormDoCmd.OpenReport以及一些其他的DoCmd语句,但它不工作DoCmd.RunSQL,过滤器,DAO和ADO。

实施范例

DoCmd.SetParameter "MyParameter", Me.MyTextbox
DoCmd.OpenForm "MyForm",,, "ID = MyParameter"

使用DAO

在DAO中,我们可以使用DAO.QueryDef对象创建查询,设置参数,然后打开记录集或执行查询。您首先设置查询的SQL,然后使用QueryDef.Parameters集合来设置参数。

在我的示例中,我将使用隐式参数类型。如果要使它们显式,请在查询中添加一个PARAMETERS声明。

实施范例

'Execute query, unnamed parameters
With CurrentDb.CreateQueryDef("", "INSERT INTO Table1(Field1) SELECT Field1 FROM Table2 WHERE Field1 = ?p1 And Field2 = ?p2")
    .Parameters(0) = Me.Field1
    .Parameters(1) = Me.Field2
    .Execute
End With

'Open recordset, named parameters
Dim rs As DAO.Recordset
With CurrentDb.CreateQueryDef("", "SELECT Field1 FROM Table2 WHERE Field1 = FirstParameter And Field2 = SecondParameter")
    .Parameters!FirstParameter = Me.Field1 'Bang notation
    .Parameters("SecondParameter").Value = Me.Field2 'More explicit notation
    Set rs = .OpenRecordset
End With

尽管仅在DAO中可用,但是您可以为DAO记录集设置许多内容,以使它们使用参数,例如表单记录集,列表框记录集和组合框记录集。但是,由于Access在排序和筛选时使用的是文本而不是记录集,因此如果您这样做,则可能会出现问题。

使用ADO

您可以通过使用ADODB.Command对象在ADO中使用参数。使用Command.CreateParameter创建的参数,然后将它们添加Command.Parameters收藏。

您可以使用.ParametersADO中的集合来显式声明参数,或将参数数组传递给Command.Execute方法以隐式传递参数。

ADO不支持命名参数。虽然您可以传递名称,但不会对其进行处理。

实施示例:

'Execute query, unnamed parameters
Dim cmd As ADODB.Command
Set cmd = New ADODB.Command
With cmd
    Set .ActiveConnection = CurrentProject.Connection 'Use a connection to the current database
    .CommandText = "INSERT INTO Table1(Field1) SELECT Field1 FROM Table2 WHERE Field1 = ? And Field2 = ?"
    .Parameters.Append .CreateParameter(, adVarWChar, adParamInput, Len(Me.Field1), Me.Field1) 'adVarWChar for text boxes that may contain unicode
    .Parameters.Append .CreateParameter(, adInteger, adParamInput, 8, Me.Field2) 'adInteger for whole numbers (long or integer)
    .Execute
End With

'Open recordset, implicit parameters
Dim rs As ADODB.Recordset
Dim cmd As ADODB.Command
Set cmd = New ADODB.Command
With cmd
    Set .ActiveConnection = CurrentProject.Connection 'Use a connection to the current database
    .CommandText = "SELECT Field1 FROM Table2 WHERE Field1 = @FirstParameter And Field2 = @SecondParameter"
     Set rs = .Execute(,Array(Me.Field1, Me.Field2))
End With

适用与打开DAO记录集相同的限制。尽管这种方式仅限于执行查询和打开记录集,但是您可以在应用程序中的其他位置使用这些记录集。



 类似资料:
  • 首先,我想说我从来没有使用过Next.js或context api,所以请耐心听我说。 我目前正在Next.js中开发一个web应用程序,其中有多个页面,每个页面都包含一个表单。我希望有某种全局状态,以便能够设置和更新每个表单的数据。所有表单数据一起 例如:第1页=名称,第2页=说明,... 从我在网上读到的内容来看,我认为使用上下文api就足够了,但我遇到了困难。当我在第一个表单上填写名字时,它

  • 在传统的web.xml类型配置中,您可以像这样配置上下文参数 web.xml 这是如何在Spring启动中实现的。我有一个需要参数的过滤器。 我使用的是,并包含了

  • 问题内容: 我一直在使用mgo作为我的API,但我在MongoDB中看到了许多当前连接(同时使用少于5个设备进行测试)。通过在Mongo服务器上执行,我得到:。在下面,我将我的问题记录在mgo的Github中(问题#429): 我在Web服务器中使用mgo的方式是否正确?如果没有,您能举一个完整的例子吗? 此代码不起作用,将其视为几乎伪代码(由于缺少诸如导入的部分或配置来自何处和模型),但这正是我

  • 问题内容: 我正在尝试在我的应用程序上使用React 16.3中的新上下文API进行一些测试,但我不明白为什么我的重定向永远无法工作。 我不想让我的ContextB可用于所有路由,仅2和3。我该怎么做? 问题答案: 看起来应该只具有和`<Redirect `组件作为直接子代。(来源) 我想这就是为什么你的,你使用不工作的孩子。 最简单但重复的解决方案可能是让您成为每个想要的孩子的孩子: 注意:这些

  • 问题内容: 我有一个验证并保存表单的视图。保存表单后,我想重定向回list_object视图,并显示一条成功消息“客户xyz的表单已成功更新…” HttpResponseRedirect似乎无法正常工作,因为它只为url提供一个参数,无法与之一起传递字典。 我已经尝试修改object_list的包装,以将dict作为具有必要上下文的参数。我从保存表单的视图内部返回对此包装的调用。但是,呈现页面时,

  • 我试图在我的应用程序上用React 16.3的新上下文API做一些测试,但是我不明白为什么我的重定向从来没有工作过。 我不想让我的ContextB适用于所有路线,只适用于2号和3号路线。我该怎么做?