如何在Microsoft Access中的不同上下文中在VBA中使用参数? [英] How do I use parameters in VBA in the different contexts in Microsoft Access?
问题描述
我从诸如 bobby-tables.com .但是,我正在Access中使用一个复杂的应用程序,该应用程序具有很多动态SQL,并且在各种地方都有字符串连接.
I've read a lot about SQL injection, and using parameters, from sources like bobby-tables.com. However, I'm working with a complex application in Access, that has a lot of dynamic SQL with string concatenation in all sorts of places.
我想更改以下内容并添加参数,以避免错误并允许我使用单引号处理名称,例如Jack O'Connel.
It has the following things I want to change, and add parameters to, to avoid errors and allow me to handle names with single quotes, like Jack O'Connel.
它使用:
-
DoCmd.RunSQL
执行SQL命令 - DAO记录集
- ADODB记录集
- 使用
WhereCondition
参数中的字符串连接以DoCmd.OpenForm
和DoCmd.OpenReport
打开的表单和报告 - 使用字符串连接的域聚集(例如
DLookUp
)
DoCmd.RunSQL
to execute SQL commands- DAO recordsets
- ADODB recordsets
- Forms and reports, opened with
DoCmd.OpenForm
andDoCmd.OpenReport
, using string concatenation in theWhereCondition
argument - Domain aggregates like
DLookUp
that use string concatenation
查询的结构大致如下:
DoCmd.RunSQL "INSERT INTO Table1(Field1) SELECT Field1 FROM Table2 WHERE ID = " & Me.SomeTextbox
在这些不同类型的查询中使用参数时,我有哪些选择?
What are my options to use parameters for these different kinds of queries?
该问题旨在作为一种资源,因为我经常在各种帖子中使用如何使用参数注释
推荐答案
有很多方法可以在查询中使用参数.我将尝试为其中的大多数示例以及适用的示例提供示例.
There are many ways to use parameters in queries. I will try to provide examples for most of them, and where they are applicable.
首先,我们将讨论Access特有的解决方案,例如表单,报表和域聚合.然后,我们将讨论DAO和ADO.
First, we'll discuss the solutions unique to Access, such as forms, reports and domain aggregates. Then, we'll talk about DAO and ADO.
在Access中,您可以直接在SQL代码中使用表单和报表上控件的当前值.这限制了对参数的需求.
In Access, you can directly use the current value of controls on forms and reports in your SQL code. This limits the need for parameters.
您可以通过以下方式引用控件:
You can refer to controls in the following way:
Forms!MyForm!MyTextbox
用于对表单进行简单控制
Forms!MyForm!MyTextbox
for a simple control on a form
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
When using DoCmd.RunSQL
, normal queries (in the GUI), form and report record sources, form and report filters, domain aggregates, DoCmd.OpenForm
and DoCmd.OpenReport
该功能不可用于以下用途:
This is not available for the following uses:
使用DAO或ADODB执行查询时(例如,打开记录集,CurrentDb.Execute
)
When executing queries using DAO or ADODB (e.g. opening recordsets, CurrentDb.Execute
)
TempVars是全局可用的变量,可以在VBA中或使用宏进行设置.它们可以重复用于多个查询.
TempVars in Access are globally available variables, that can be set in VBA or using macro's. They can be reused for multiple queries.
示例实施:
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,可用于其他用途.
Availability for TempVars is identical to that of values from forms and reports: not available for ADO and DAO, available for other uses.
我建议使用TempVars在打开窗体或报告引用控件名称时使用参数,因为如果打开它的对象关闭,则TempVars仍然可用.我建议为每个表单或报表使用唯一的TempVar名称,以避免在刷新表单或报表时出现怪异现象.
I recommend TempVars for using parameters when opening forms or reports over referring to control names, since if the object opening it closes, the TempVars stay available. I recommend using unique TempVar names for every form or report, to avoid weirdness when refreshing forms or reports.
与TempVars一样,您可以使用自定义函数和静态变量来存储和检索值.
Much like TempVars, you can use a custom function and static variables to store and retrieve values.
示例实施:
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()"
此外,可能会创建带有可选参数的单个函数,用于设置和获取私有静态变量的值:
Also, a single function with an optional parameter may be created for both setting and getting the value of a private static variable:
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.OpenForm
,DoCmd.OpenReport
和某些其他DoCmd
语句的参数,但不适用于DoCmd.RunSQL
,过滤器,DAO和ADO.
Using DoCmd.SetParameter
The uses of DoCmd.SetParameter
are rather limited, so I'll be brief. It allows you to set a parameter for use in DoCmd.OpenForm
, DoCmd.OpenReport
and some other DoCmd
statements, but it doesn't work with DoCmd.RunSQL
, filters, DAO and ADO.
示例实施
DoCmd.SetParameter "MyParameter", Me.MyTextbox
DoCmd.OpenForm "MyForm",,, "ID = MyParameter"
使用DAO
在DAO中,我们可以使用DAO.QueryDef
对象创建查询,设置参数,然后打开记录集或执行查询.首先设置查询的SQL,然后使用QueryDef.Parameters
集合设置参数.
Using DAO
In DAO, we can use the DAO.QueryDef
object to create a query, set parameters, and then either open up a recordset or execute the query. You first set the queries' SQL, then use the QueryDef.Parameters
collection to set the parameters.
在我的示例中,我将使用隐式参数类型.如果要使其明确,请添加 PARAMETERS
声明进入您的查询.
In my example, I'm going to use implicit parameter types. If you want to make them explicit, add a PARAMETERS
declaration to your query.
示例实施
'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在排序和筛选时使用的是文本而不是记录集,因此如果您这样做,这些事情可能会成为问题.
While this is only available in DAO, you can set many things to DAO recordsets to make them use parameters, such as form recordsets, list box recordsets and combo box recordsets. However, since Access uses the text, and not the recordset, when sorting and filtering, those things may prove problematic if you do.
您可以通过使用ADODB.Command
对象在ADO中使用参数.使用Command.CreateParameter
创建参数,然后将它们附加到Command.Parameters
集合.
You can use parameters in ADO by using the ADODB.Command
object. Use Command.CreateParameter
to create parameters, and then append them to the Command.Parameters
collection.
您可以在ADO中使用.Parameters
集合来显式声明参数,或将参数数组传递给Command.Execute
方法以隐式传递参数.
You can use the .Parameters
collection in ADO to explicitly declare parameters, or pass a parameter array to the Command.Execute
method to implicitly pass parameters.
ADO不支持命名参数.虽然您可以传递名称,但不会对其进行处理.
ADO does not support named parameters. While you can pass a name, it's not processed.
示例实施:
'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记录集的限制相同.尽管这种方法仅限于执行查询和打开记录集,但是您可以在应用程序中的其他位置使用这些记录集.
The same limitations as opening DAO recordsets apply. While this way is limited to executing queries and opening recordsets, you can use those recordsets elsewhere in your application.
这篇关于如何在Microsoft Access中的不同上下文中在VBA中使用参数?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!