2014-12-13 50 views
1

錯誤:「運行時錯誤‘3061’參數太少預計2錯誤的一個記錄,但相同的SQL工作別處

我寫了這個簡單的函數,返回的記錄數計算的剩餘百分比變化。它應該是當用戶更新名爲「百分比」我確信下面的代碼應該工作,但是很明顯的東西是錯誤的領域發生它發生就行了。

Set rs = db.OpenRecordset("SELECT Tier1, [Percentage], Tier3 AS Battalion, Month " _ 
    & "FROM tbl_CustomPercent " _ 
    & "WHERE (((Tier1)=[Forms]![frmEntry]![cmbImport_T1]) AND ((Month)=[Forms]![frmEntry]![cmbMonth]));", dbOpenSnapshot) 

我不知道它可能會失敗當完全相同的查詢是使用「百分比」文本框填充表單的「記錄源」時

Function RemainingPercentAvailable() As String 
Dim db As DAO.Database 
Dim rs As DAO.Recordset 
Dim strSQL As String 


Set db = CurrentDb 
Set rs = db.OpenRecordset("SELECT Tier1, [Percentage], Tier3 AS Battalion, Month " _ 
& "FROM tbl_CustomPercent " _ 
& "WHERE (((Tier1)=[Forms]![frmEntry]![cmbImport_T1]) AND ((Month)=[Forms]![frmEntry]![cmbMonth]));", dbOpenSnapshot) 

Dim CurrentTotal As Single 

CurrentTotal = 0 

If Not (rs.EOF And rs.BOF) Then 
    rs.MoveFirst 

    Do Until rs.EOF = True 
     CurrentTotal = CurrentTotal + rs!Percentage 
     rs.MoveNext 
    Loop 

End If 


RemainingPercentAvailable = "Remaing available: " & Format(1 - CurrentTotal, "0.000%") 

Set rs = Nothing 
Set db = Nothing 

End Function 

回答

2

調整您的代碼以使用QueryDef的SELECT語句,爲參數提供值,然後從QueryDef打開記錄集。

Dim db As DAO.Database 
Dim qdf As DAO.QueryDef 
Dim rs As DAO.Recordset 
Dim strSQL As String 

strSQL = "SELECT Tier1, [Percentage], Tier3 AS Battalion, [Month] " _ 
    & "FROM tbl_CustomPercent " _ 
    & "WHERE (((Tier1)=[Forms]![frmEntry]![cmbImport_T1]) AND (([Month])=[Forms]![frmEntry]![cmbMonth]));" 

Set db = CurrentDb 
Set qdf = db.CreateQueryDef(vbNullString, strSQL) 
' supply values for the 2 parameters ... 
qdf.Parameters(0).Value = Eval(qdf.Parameters(0).Name) 
qdf.Parameters(1).Value = Eval(qdf.Parameters(1).Name) 
Set rs = qdf.OpenRecordset 

注意:Month是保留字。雖然這個名字顯然沒有引起任何問題,但我把它放在方括號中,因此數據庫引擎不能將字段名稱與Month函數混淆。這可能是一個不必要的預防措施,但很難準確預測保留字是什麼時候會產生問題。事實上,如果可能的話最好避免它們。

+0

這確實奏效。謝謝。我想知道爲什麼我有其他例子偶爾起作用? – monty327 2014-12-13 18:24:32

+0

對於那些工作的實例,你是否直接以DAO.Recordset方式打開查詢? – HansUp 2014-12-13 18:27:25

+0

這是另一個實例: – monty327 2014-12-14 18:32:31

0

這是直接在DAO.Recordset中調用查詢,它工作得很好。
請注意相同的'Set rs = db.OpenRecordset(strSQL,dbOpenDynaset)這也是一個參數SQL。 唯一的區別是這個是我不需要移動和分析記錄集 - 但錯誤發生在'Set rs ='行上,所以我無法進一步獲得進一步的信息。

昏暗RS作爲DAO.Recordset 昏暗分貝作爲DAO.DATABASE 昏暗STRSQL作爲字符串

STRSQL = 「SELECT SUM(tbl_SP.AFP)AS AFP_TOTAL,tbl_SP.T1_UNIT」 _ & 「FROM tbl_SP」 _ & 「(GROUP BY tbl_SP.T1_UNIT」_ &「HAVING((((tbl_SP.T1_UNIT)=''& strUnit & 「」));「

集DB = CurrentDb 集RS = db.OpenRecordset(STRSQL,dbOpenDynaset)

AFP_Total = RS AFP_Total

-1

我不建議建立一個臨時的參數化查詢!在VBA中,因爲它使代碼太複雜。並且變慢。我更喜歡構建「純」的SQL,它將直接在數據庫引擎中運行,而無需對Access進行任何回調。我假設您的函數是在frmEntry窗體中定義的,並且cmbImport_T1cmbMonth是字符串字段。如果它們是數字,則省略qString()

這是我的版本的函數。它正確處理空記錄集的情況。

Function RemainingPercentAvailable() As String 
Dim CurrentTotal As Double, q As String 
q = "SELECT Percentage" & _ 
    " FROM tbl_CustomPercent" & _ 
    " WHERE Tier1 = " & QString(cmbImport_T1) & _ 
    " AND [Month] = " & QString(cmbMonth) 
CurrentTotal = 0 
With CurrentDb.OpenRecordset(q) 
    While Not .EOF 
    CurrentTotal = CurrentTotal + .Fields("Percentage") 
    .MoveNext 
    Wend 
End With 
RemainingPercentAvailable = "Remaining available: " & _ 
          Format(1 - CurrentTotal, "0.000%") 
End Function 

' Return string S quoted, with quotes escaped, for building SQL. 
Public Function QString(ByVal S As String) As String 
    QString = "'" & Replace(S, "'", "''") & "'" 
End Function 
+0

謝謝湯姆解決這些問題,儘管他們不是這個問題的標題。該操作很好地工作。我要去詢問其他地方的第二部分,但自從你回答以後,我似乎無法弄清楚爲什麼計算結果偏離了15%。嘗試在6條記錄上執行它,百分比值爲.25,.1,.1,.2,.2和.15。它返回「剩餘可用:15.000%」 - 無法想象爲什麼 - 顯然錯過了其他的東西 – monty327 2014-12-14 21:50:36

+1

*您可能「更喜歡構建'直接在數據庫引擎中運行的'純SQL',但是可以使用全面的建議動態SQL對參數化查詢只是一個糟糕的建議,你聲稱參數化查詢使得代碼「更復雜」(而不是使用VBA函數進行可怕的字符串連接來清理和格式化參數?)和「更慢」(真的?*顯着*和*可以*慢一些),而忽略**(1)**防止SQL注入的優點,**(2)**避免文本分隔符錯誤,**(3)**不必擔心'dd/mm'和'mm/dd'的日期格式 – 2014-12-14 23:06:50

+0

Monty - 它對我有用!不知何故,你並沒有在總數中加入最後的數字,試着在之前添加'debug.print .Fields(「Percentage」)看看你的輸出是否爲0.15,如果你現在不能複製這個問題,那麼也許你的表單有問題。如果您重新計算表單上txtPercentage_AfterUpdate事件的剩餘百分比,則新值將不會寫入數據庫。嘗試在事件過程開始時添加'Me.Dirty = False'。 – 2014-12-14 23:10:23

0

有一種更簡單的方法來計算總百分比。

您可以使用DSum()函數代替循環記錄。

請注意,如果沒有記錄,DSum將返回Null,因此您需要將其包裝在Nz()中。

只是爲了好玩,這裏是你的功能,但寫成一個單獨的語句:

Function RemainingPercentAvailable() As String 
    RemainingPercentAvailable = "Remaining available: " & Format(1 - _ 
     Nz(DSum("Percentage", _ 
       "tbl_CustomPercent", _ 
       "Tier1 = " & QString(cmbImport_T1) & _ 
       " AND [Month] = " & QString(cmbMonth))) _ 
     , "0.000%") 
    End Function 
相關問題