尝试将子表单记录源设置为 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 查询时出错的主要内容,如果未能解决你的问题,请参考以下文章

打开记录集 MSAccess 时出错

尝试将记录添加到具有先前创建的记录的表时出错

尝试使用 min 子查询查找记录时 Hive 出错

运行 MySQL 循环时出错

尝试将 sql 查询详细说明到 cakephp 时总是出错;如何转换这个?

尝试在 SQL Plus 查询中小写列时出错