尝试将子表单记录源设置为 sql 查询时出错
Posted
技术标签:
【中文标题】尝试将子表单记录源设置为 sql 查询时出错【英文标题】:Error when trying to set the subform recordsource to an sql query 【发布时间】:2017-10-25 17:04:29 【问题描述】:我正在尝试更改子表单的记录集以显示查询结果
所以我有一个字符串查询:
sQueryCurrencyRate = "SELECT * FROM Table.Mytable WHERE As_Of_Date =" & Format(dateField.value, "M/d/yyyy")
sQueryCurrencyUsDollar = "SELECT * FROM Table.Mytable WHERE As_Of_Date =" & Format(dateField.value, "M/d/yyyy")
所以当我写这个的时候,子表单会显示一个没有错误的结果:
Me.subformName.Form.RecordsourceSourceObject = "Table.tableName"
但是当我尝试以下所有方法时,我总是收到错误:
Forms!formName.subformName.Form.RecordSource= sQueryCurrencyRate
我也试过了:
Me.subFormName.Form.RecordsourceSourceObject= sQueryCurrencyRate
还有,
Me.subFormName.RecordsourceSourceObject= sQueryCurrencyRate
无论我做什么,我总是会收到此错误消息:
您输入的表达式引用了一个关闭的对象或 不存在
我做错了什么?以及如何在子表单记录源中正确显示查询结果?
P.S: sql 查询语法很好,因为我之前用过:
Set db = CurrentDb
Set rs = db.OpenRecordset(sQueryCurrencyRate)
我没有收到错误,所以问题是如何将子表单结果绑定到查询
编辑:
我调用代码的方式如下:
Function detectSelectedQuery(sTypeDonnee As String)
sQueryCurrencyRate = "SELECT * FROM Table.Mytable WHERE As_Of_Date = ' " & Format(dateField.value, "M/d/yyyy") &"'"
Me![Child8].Form.RecordSource = sQueryCurrencyRate
end function
然后当组合框改变时,我调用函数:
Private Sub Combo_descriptionQueries_Change()
detectSelectedQuery (Combo_descriptionQueries.Value)
End Sub
【问题讨论】:
@ErikvonAsmuth 我也试过简单地做 'me.subformName.Form.RecordSource= sQueryCurrencyRate' 和 'me.subformName.RecordSource= sQueryCurrencyRate' 没有任何成功,这很奇怪 你在哪里调用这个代码?在主窗体上? @ErikvonAsmuth 我已经声明了一个名为 Execute Query 的函数,在它内部,我正在调用代码 @Mat'sMug 整个RecordSetObject
部分是错误的,他打算设置RecordSource
,这是表单使用的字符串SQL 语句(也有RecordSet
属性,但是除非您想使用 ADO 记录集作为记录源,否则不应更改)
@ErikvonAsmuth 我会用四根手指和一条腿换取正确参数化的 ADODB 记录集/查询,而不是像这样的字符串连接、乞求 SQL 注入 WHERE
子句。当然,它使得到有效的东西变得“容易”,但在很多层面上都是完全错误的。例如,UserForms and their default instance 也是如此。太多东西在 VBA 中被简化了,简直太疯狂了。
【参考方案1】:
如果您想正确执行此操作(没有任何 SQL 注入风险),您可以使用 ADODB 记录集:
Dim cmd As New ADODB.Command
cmd.CommandText = "SELECT * FROM Mytable WHERE As_Of_Date = @MyDate"
cmd.ActiveConnection = CurrentProject.Connection
cmd.ActiveConnection.CursorLocation = adUseClient
cmd.Parameters("@MyDate") = cmd.CreateParameter("MyDate", adDate)
cmd.Parameters("@MyDate").Value = datefield.Value
Set Me.Recordset = cmd.Execute
请注意,这需要引用 ActiveX 数据对象库
【讨论】:
我认为cmd.Parameters("@MyDate")
赋值应该是Set
,因为CreateParameter
返回一个ADODB.Parameter
对象引用。无论属性 mutator 的值是否接收到 Variant
,它都可能工作,它将保存指向对象引用的指针。另外我认为您可以删除 rs
局部变量和 Set Me.Recordset = cmd.Execute
@Mat'sMug 你对第二个是正确的,但是第一个(将cmd.Parameters
赋值更改为Set
会导致编译错误(属性的无效使用)对我来说. 不知道为什么,但它可以在没有Set
的情况下工作,也不能与Set
有趣。我通常做cmd.Parameters.Append cmd.CreateParameter(...)
【参考方案2】:
使用这个:
sQueryCurrencyRate = "SELECT * FROM Mytable WHERE As_Of_Date = #" & Format(dateField.value, "yyyy\/mm\/dd") & "#"
为避免连接,您可以使用 TempVars 或创建一个小型辅助函数:
' Public variable:
Dim FilterDate As Date
Public Function GetFilterDate() As Date
GetFilterDate = FilterDate
End Function
然后是额外的一行代码:
FilterDate = Me!dateField.Value
sQueryCurrencyRate = "SELECT * FROM Mytable WHERE As_Of_Date = GetFilterDate()"
【讨论】:
对正确的 date literal 分隔符表示敬意...有没有办法避免字符串连接?【参考方案3】:既然这是在 Access 中,为什么不使用带有参数查询的默认 DAO 接口而不是 ADODB?不需要 ActiveX 数据对象引用。
Dim qdf As DAO.QueryDef
'For an existing query
Set qdf = CurrentDb().QueryDefs("qryName")
'To create query (Credit to @Erik von Asmuth for pointing this out)
Set qdf = CurrentDb().CreateQueryDef("", "PARAMETERS [@MyDate] DateTime; SELECT * FROM Mytable WHERE As_Of_Date = [@MyDate];")
qdf.Parameters("[@MyDate]").Value = Date()
Set Me.Recordset = qdf.OpenRecordset()
【讨论】:
这是一个有效的替代方案。我以前从未将Me.RecordSet
设置为 DAO 记录集,因为我一直只是针对这种行为使用过滤器(我已经将 ADO 记录集用于外部数据库,因此对此有一些经验。您可能想要替换 @987654323 @ 和 .CreateQueryDef("", "SELECT * FROM Table.Mytable WHERE As_Of_Date = [@MyDate]")
更适用于该问题,但考虑到未存储的查询。
通常,参数定义可以省略,但插入它当然是一个好习惯,特别是如果你依赖于类型转换以上是关于尝试将子表单记录源设置为 sql 查询时出错的主要内容,如果未能解决你的问题,请参考以下文章