簡體   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