使用嵌套查询打开记录集

时间:2019-04-23 15:53:19

标签: ms-access access-vba

我正在尝试在Access VBA中打开一个记录集。我在VBA中写了我的SQL字符串,因为我正在使用带有变量的Select Top。当前,我遇到运行时错误3061-参数太少。预期1

我的SQL字符串正在将表单填充为RecordSource,因此我知道该字符串可以正常工作。当我尝试打开该记录集以进一步处理数据时,就会出现我的问题。

我认为此错误是由于我的SQL字符串正在引用数据库中的其他两个查询而导致的。有办法解决参数错误吗?

这是我的代码。抱歉,如果格式不正确

Private Sub Form_Load()

Dim skip As String
Dim sqlstr As String

skip = "select [skip lot qty] from [Requirements] where [requirements].[part no] = eval('[forms]![main menu]![part no]')"


Dim rs As DAO.Recordset
Set rs = CurrentDb.OpenRecordset(skip)


Dim SLQ As Integer

SLQ = rs![skip lot qty]

Dim vendor As String
vendor = [Forms]![Main Menu]![Vendor No]

sqlstr = "SELECT TOP " & SLQ & " [Vendor Log].[ID],[Vendors Query].[Vendor Name], [Vendor Log].[Vendor No], [Vendor Log].[Date], [Vendors Query].[Last Qtr Rating], "

sqlstr = sqlstr & "[Vendor Log].[Part No] , [Requirements Query].[Skip Lot], [Requirements Query].[Plan No], [Vendor Log].[Inspection Req'd], [Vendor Log].[PO Number], "

sqlstr = sqlstr & "[Vendor Log].[Qty Received], [Vendor Log].[Sample Qty], [Vendor Log].[Accept Lot], [Vendor Log].[Comments], [Vendor Log].[Inspector Clock No], "

sqlstr = sqlstr & "[Vendor Log].[Counter], [Requirements Query].[Rev Date], [Requirements Query].[Rev Note], IIf([Accept Lot]=""R"",1,0) AS [R Counter], "

sqlstr = sqlstr & "IIf([Inspection Req'd]=""Yes"",1,0) AS [Yes Counter], IIf([Dim A]=""N/A"",""No"",""Yes"") AS [Dim Insp], IIf([Accept Lot] Is Null,1,0) AS"

sqlstr = sqlstr & " [Null Counter], [Requirements Query].[skip lot qty] FROM [Vendors Query] INNER JOIN ([Requirements Query] INNER JOIN [Vendor Log] ON "

sqlstr = sqlstr & " [Requirements Query].[Part No] = [Vendor Log].[Part No]) ON [Vendors Query].[Vendor No] = [Vendor Log].[Vendor No]"

sqlstr = sqlstr & " WHERE ((([Vendor Log].Date) > (Date - 1095)) And (([Vendor Log].[Vendor No]) = '" & vendor & "')) ORDER BY [Vendor Log].[ID] DESC;"

Debug.Print sqlstr
''setting the record source of the form to the string
Me.RecordSource = sqlstr

Dim rs2 As DAO.Recordset
Dim db As DAO.Database


Set db = CurrentDb


Set rs2 = db.OpenRecordset(sqlstr) >>this is the error

“供应商日志”是一个表,而“需求查询”和“供应商查询”是使用上一表格中的信息引用表的选择查询。

我想打开此记录集,以便对字符串中的不同计数器求和。

我已将sqlstr粘贴到新查询中,并且运行良好。我已经仔细检查了所有表名,并顺利通过数据库运行了需求查询和供应商查询。

请帮助!

编辑:Debug.Print的输出:

SELECT TOP 4 [Vendor Log].[ID],[Vendors Query].[Vendor Name], [Vendor Log].[Vendor No], [Vendor Log].[Date], [Vendors Query].[Last Qtr Rating], [Vendor Log].[Part No] , [Requirements Query].[Skip Lot], [Requirements Query].[Plan No], [Vendor Log].[Inspection Req'd], [Vendor Log].[PO Number], [Vendor Log].[Qty Received], [Vendor Log].[Sample Qty], [Vendor Log].[Accept Lot], [Vendor Log].[Comments], [Vendor Log].[Inspector Clock No], [Vendor Log].[Counter], [Requirements Query].[Rev Date], [Requirements Query].[Rev Note], IIf([Accept Lot]="R",1,0) AS [R Counter], IIf([Inspection Req'd]="Yes",1,0) AS [Yes Counter], IIf([Dim A]="N/A","No","Yes") AS [Dim Insp], IIf([Accept Lot] Is Null,1,0) AS [Null Counter], [Requirements Query].[skip lot qty] FROM [Vendors Query] INNER JOIN ([Requirements Query] INNER JOIN [Vendor Log] ON  [Requirements Query].[Part No] = [Vendor Log].[Part No]) ON [Vendors Query].[Vendor No] = [Vendor Log].[Vendor No] WHERE ((([Vendor Log].Date) > (Date - 1095)) And (([Vendor Log].[Vendor No]) = 'PO1296')) ORDER BY [Vendor Log].[ID] DESC;

编辑2: 抱歉,这是很长的查询!这是“需求”查询。 [零件编号]是表格,[要求]是表格

SELECT DISTINCTROW TOP 1 [Part Numbers].[Part No], [Part Numbers].Description, [Part Numbers].[Matl Type], [Part Numbers].Illustration, [Part Numbers].Obsolete, [Part Numbers].UOM, Requirements.[Skip Lot], Requirements.[Plan No], Requirements.Material, Requirements.[ID Reference], Requirements.Comment, Requirements.Functional, Requirements.Finish, Requirements.Cosmetic, Requirements.[Packaging - General], Requirements.[Individual Label/Tag], Requirements.[UPC Code], Requirements.[Qty per Pack], Requirements.[Pack Label], Requirements.[I2of5 Pack], Requirements.[Qty per Case], Requirements.[Case Label], Requirements.[I2of5 Case], Requirements.[Case Check Req'd?], Requirements.[Case Length (In)], [Case Length (In)]-([Case Length (In)]*0.15) AS [Case L Min], [Case Length (In)]+([Case Length (In)]*0.15) AS [Case L Max], Requirements.[Case Width (In)], [Case Width (In)]-([Case Width (In)]*0.15) AS [Case W Min], [Case Width (In)]+([Case Width (In)]*0.15) AS [Case W Max], Requirements.[Case Height (In)], [Case Height (In)]-([Case Height (In)]*0.15) AS [Case H Min], [Case Height (In)]+([Case Height (In)]*0.15) AS [Case H Max], Requirements.[Case Weight], [Case Weight]-([Case Weight]*0.15) AS [Case Wt Min], [Case Weight]+([Case Weight]*0.15) AS [Case Wt Max], Requirements.Certs, Requirements.[Dim A], Requirements.[A Tolerance], Requirements.[Dim B], Requirements.[B Tolerance], Requirements.[Dim C], Requirements.[C Tolerance], Requirements.[Dim D], Requirements.[D Tolerance], Requirements.[Dim E], Requirements.[E Tolerance], Requirements.[Dim F], Requirements.[F Tolerance], Requirements.[Dim G], Requirements.[G Tolerance], Requirements.[Dim H], Requirements.[H Tolerance], Requirements.[Other Dim], Requirements.[Other Tol], Requirements.[WLL (lbs)], Requirements.[WLL (kg)], Requirements.[BF Test Data], Requirements.[Breaking Force (lbs)], Requirements.[BF Test Req'd?], Requirements.[BF Sample], Requirements.Elongation, Requirements.Comments, Requirements.[Rev Date], Requirements.[Rev Note], IIf([Dim A]="N/A","No","Yes") AS [Dim Insp], Requirements.[Spec Ref], Requirements.[skip lot qty]
FROM [Part Numbers] INNER JOIN Requirements ON [Part Numbers].[Part No] = Requirements.[Part No]
WHERE ((([Part Numbers].[Part No])=[Forms]![Main Menu]![Part No]))
ORDER BY Requirements.[Rev Date] DESC;

供应商查询:供应商和评级都是表格

SELECT Vendors.[Vendor No], Vendors.[Vendor Name], Vendors.Obsolete, Vendors.[Last Qtr Rating], Ratings.[Last Rating Score]
FROM Ratings INNER JOIN Vendors ON Ratings.[Last Qtr Rating] = Vendors.[Last Qtr Rating]
WHERE (((Vendors.Obsolete)=No))
ORDER BY Vendors.[Vendor Name];

1 个答案:

答案 0 :(得分:1)

您遇到的问题是由于Database.OpenRecordset无法与包含参数的命名查询一起使用。您的“需求”查询包含对表单字段的引用,该表单字段是一个参数,必须使用QueryDef对象进行显式设置。

这个奇怪的怪癖也是为什么当您通过Database.OpenRecordset调用该查询时,该查询在所有其他情况下都可以接受的原因。

最简单的解决方案是将sqlstr中的SQL保存为命名查询,通过QueryDef对象打开它,设置其参数(供应商和[Forms]![Main Menu]![Part]否]),然后通过调用QueryDef.OpenRecordset打开记录集。

代码看起来类似于:

    Dim qdf as QueryDef
    Set qdf = CurrentDb.QueryDefs("namedQuery") ' replace with name of new query

' optionally, use this RegExp to replace "SELECT TOP n" dynamically
' requires reference: Microsoft VBScript Regular Expressions 5.5
'    Dim regex As New RegExp
'    regex.IgnoreCase = True
'    regex.Global = True
'    regex.Pattern = "(SELECT TOP )[0-9]+"
'    qdf.SQL = regex.Replace(qdf.SQL, "SELECT TOP " & rs![skip lot qty])

    qdf.Parameters("vendor") = [Forms]![Main Menu]![Vendor No]
    qdf.Parameters("[Forms]![Main Menu]![Part No]") = [Forms]![Main Menu]![Part No]

    Set rs2 = qdf.OpenRecordset
    qdf.Close

新命名的查询如下所示(通知供应商参数):

SELECT TOP 4 [Vendor Log].[ID],[Vendors Query].[Vendor Name], [Vendor Log].[Vendor No], [Vendor Log].[Date], [Vendors Query].[Last Qtr Rating], [Vendor Log].[Part No] , [Requirements Query].[Skip Lot], [Requirements Query].[Plan No], [Vendor Log].[Inspection Req'd], [Vendor Log].[PO Number], [Vendor Log].[Qty Received], [Vendor Log].[Sample Qty], [Vendor Log].[Accept Lot], [Vendor Log].[Comments], [Vendor Log].[Inspector Clock No], [Vendor Log].[Counter], [Requirements Query].[Rev Date], [Requirements Query].[Rev Note], IIf([Accept Lot]="R",1,0) AS [R Counter], IIf([Inspection Req'd]="Yes",1,0) AS [Yes Counter], IIf([Dim A]="N/A","No","Yes") AS [Dim Insp], IIf([Accept Lot] Is Null,1,0) AS [Null Counter], [Requirements Query].[skip lot qty] FROM [Vendors Query] INNER JOIN ([Requirements Query] INNER JOIN [Vendor Log] ON  [Requirements Query].[Part No] = [Vendor Log].[Part No]) ON [Vendors Query].[Vendor No] = [Vendor Log].[Vendor No] WHERE ((([Vendor Log].Date) > (Date - 1095)) And (([Vendor Log].[Vendor No]) = vendor)) ORDER BY [Vendor Log].[ID] DESC;

编辑:正如HansUp指出的,TOP仅接受文字,不接受参数。您可以在查询中静态指定TOP n,或者如果表不是很大(10,000条以上的记录),则将其全部删除。或者,您也可以使用上面代码中包含的正则表达式

HansUp的另一个优点是,不再需要RegExp。您也可以使用以下代码:

    Dim qdf as QueryDef
    Set qdf = CurrentDb.CreateQueryDef("") ' creates temporary querydef

    qdf.SQL = "SELECT TOP " & SLQ & "rest of sqlstr..."    

    qdf.Parameters("vendor") = [Forms]![Main Menu]![Vendor No]
    qdf.Parameters("[Forms]![Main Menu]![Part No]") = [Forms]![Main Menu]![Part No]

    Set rs2 = qdf.OpenRecordset
    qdf.Close