在查询中使用参数有很多方法。我将尝试为其中的大多数提供示例,以及它们适用的地方。
首先,我们将讨论 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()"
此外,可以创建一个带有 可选 参数的 single 函数,用于设置和获取私有静态变量的值:
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。
示例实现
DoCmd.SetParameter "MyParameter", Me.MyTextbox
DoCmd.OpenForm "MyForm",,, "ID = MyParameter"
使用 DAO
在 DAO 中,我们可以使用DAO.QueryDef 对象来创建查询、设置参数,然后打开记录集或执行查询。您首先设置查询的 SQL,然后使用 QueryDef.Parameters 集合设置参数。
在我的示例中,我将使用隐式参数类型。如果您想让它们明确,请在查询中添加 PARAMETERS declaration。
示例实现
'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 集合中。
您可以使用ADO中的.Parameters集合显式声明参数,或者将参数数组传递给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 记录集相同的限制。虽然这种方式仅限于执行查询和打开记录集,但您可以在应用程序的其他地方使用这些记录集。