繁体   English   中英

访问VBA:查询不返回任何行

[英]Access VBA: Query returns no rows

我写了一些VBA:

For x = LBound(resProdID) To UBound(resProdID)
    CurrentDb.QueryDefs("qry_findID_vba").SQL = "" & _
    "SELECT tbl_products.ProdID " & _
    "FROM tbl_products " & _
    "WHERE (tbl_products.Size = " & resSize(x) & " " & _
    "AND tbl_products.SupplID = '" & Forms.frm_suppliers.SupplID & "')"

    Dim dbs As DAO.Database
    Dim rst As DAO.Recordset

    Set dbs = CurrentDb()
    Set rst = dbs.OpenRecordset("qry_findID_vba")

    MsgBox rst.RecordCount

    If rst.RecordCount <> 0 Then
        rst.MoveLast
        rst.MoveFirst

        newProdID(x) = rst.Fields(0).Value
        MsgBox "This never fires"
     End If

    rst.Close
    Set rst = Nothing
    dbs.Close
    Set dbs = Nothing
Next x

当我运行它时会发生什么,是弹出一个框说0。我点击确定,然后再重复一次。 这是因为我的resProdID数组中有两个项目。

但是,如果我正常打开查询“qry_findID_vba”,它会显示一行,就像我预期的那样。

为什么VBA不返回这一行? 我做错了什么吗?

此代码消息框是否正确计数? 你可以用吗? (注意,我实际上没有运行它,所以要注意轻微的语法错误。)

For x = LBound(resProdID) To UBound(resProdID) 
    Dim sql as String
    Dim rst As DAO.Recordset 
    sql = "Select tbl_products.ProdID FROM tbl_products " & _
          "WHERE (tbl_products.Size = " & resSize(x) & " " & _
          "AND tbl_products.SupplID = '" & Forms.frm_suppliers.SupplID & "')" 
    Set rst = dbs.OpenRecordset(sql)
    if not rst.eof then 
        MsgBox rst.fields("ProdID")    
    else
        Msgbox "None found!"
    end if
    rst.Close 
    Set rst = Nothing 
Next x 

另外,尝试将所有内容复制到新表单,并压缩和修复数据库...

首先,你真的应该使用QueryDef参数。 它们提供了许多好处:

  • 防止格式错误的输入和SQL注入的安全网。
  • 每次参数值更改时,您都不需要重新定义查询SQL文本。
  • 它们使您的VBA独立于查询文本。 这是一个简单的查询,但如果您不必更改VBA代码来更改SQL,则更复杂的查询会受益。
  • 它们提供类型安全性 - 您可以在VBA中使用类型变量,并确保查询不会因数据类型错误而失败。
  • 它们可以重复使用 - 例如,参数化查询可以绑定到表单或直接执行。
  • 最后但同样重要的是,在VBA中使用它看起来更好更清晰。

您的情况正是参数化QueryDefs的用途。

在Access qry_findID_vba的查询文本更改为:

PARAMETERS [ProductSize] Text (255), [SupplID] Number;
SELECT ProdID
FROM tbl_products
WHERE [tbl_products].[Size] = [ProductSize] AND [tbl_products].[SupplID] = [SupplID];

根据表中的实际数据类型替换参数数据类型。

接下来,当您处于循环中时,不要一次又一次地重新定义固定变量。 dbsrst根本不需要在循环内定义。

最后一点, RecordCount属性不像您想象的那样工作。 从文档引用 ,强调我的:

使用RecordCount属性可以找出Recordset或TableDef对象中已访问的记录数。 在访问所有记录之前 ,RecordCount属性不指示动态集,快照或仅前向类型Recordset对象中包含的记录数。 [...]要强制访问最后一条记录,请使用Recordset对象上的MoveLast方法。

您也可以检查.EOF属性,而不是调用MoveLast 如果为false,则至少有一条记录可用。

对于像这样的一次性查询结果,我建议使用快照类型Recordset。 您可以在QueryDef上调用OpenRecordset时定义使用的类型

现在:

Dim qry_findID_vba As DAO.QueryDef 
Set qry_findID_vba = CurrentDb().QueryDefs("qry_findID_vba")

qry_findID_vba.Parameters("SupplID") = Forms.frm_suppliers.SupplID

For x = LBound(resProdID) To UBound(resProdID)
    qry_findID_vba.Parameters("ProductSize") = resSize(x)

    With qry_findID_vba.OpenRecordset(dbOpenSnapshot)
        If Not .EOF Then 
            newProdID(x) = .Fields("ProdID").Value 
        End If
    End With
Next x

请注意,我使用With来保存辅助器rst变量。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM