如何在MS Access 2003中创建参数查询并使用其他查询/表单填充参数以获取结果集

3

我希望能够在MS Access 2003中创建一个参数化查询,并将某些表单元素的值传递给该查询,然后获取相应的结果集并进行一些基本的计算。但是我不知道如何让查询的参数由表单元素填充。如果需要使用VBA,那也没关系。

5个回答

2

在Access查询中可以直接使用表单上的控件,但是重要的是将它们定义为参数(否则,在近期版本的Access中,结果可能不可预测,而它们曾经是可靠的)。

例如,如果您想按MyForm上的LastName控件过滤查询,您应该将其作为条件:

LastName = Forms!MyForm!LastName

然后,您需要将表单引用定义为参数。生成的SQL可能如下所示:

PARAMETERS [[Forms]!MyForm![LastName]] Text ( 255 );
SELECT tblCustomers.*
FROM tblCustomers
WHERE tblCustomers.LastName=[Forms]![MyForm]![LastName];

我想问一下,您为什么需要保存这个查询?你的结果用来做什么呢?是在表单或报表中显示吗?如果是的话,您可以在表单/报告的Recordsource中完成此操作,并将保存的查询保持不变,以便在其他上下文中使用而无需弹出填写参数的提示。
另一方面,如果您正在编写代码,只需即时编写SQL并使用表单控件的文字值来构建WHERE子句。

大卫是对的。如果您只想返回记录并对其进行求和等操作,并且不需要使用VBA,您可以使用他展示的语法引用表单控件作为条件。如果您需要执行比这更复杂的操作,我还建议使用VBA和动态设置RecordSource属性。 - Tim Lara

1
这是一段代码片段。它使用参数txtHospital更新表格:
Set db = CurrentDb

Set qdf = db.QueryDefs("AddHospital")
qdf.Parameters!txtHospital = Trim(Me.HospName)
qdf.ReturnsRecords = False

qdf.Execute dbFailOnError

intResult = qdf.RecordsAffected

这是 SQL 的一个示例:

PARAMETERS txtHospital Text(255); 

INSERT INTO tblHospitals ( 
[Hospital] )

VALUES ( 
[txtHospital] )

1

解决这个问题有三种传统方法:

  1. 给参数命名为一些聪明的东西,这样当查询运行时,用户将被提示输入值。
  2. 在表单上引用字段(可能是隐藏的)
  3. 动态构建查询,不使用参数。

我认为让你注入像 [?enter ISO code of the country] 或者在你的表单上引用字段,比如:[Forms]![MyForm]![LastName] 是错误的。

这意味着我们不能在多个地方重复使用相同的查询,使用不同的字段提供数据,或者依赖用户在运行查询时不会犯错。据我回忆,使用用户输入的参数可能很难多次使用相同的值。

通常我选择最后一个选项,即动态构建查询,并根据需要更新查询对象。然而,这容易受到 SQL 注入攻击(无论是意外还是故意的),而且很恶心。

所以我进行了一些挖掘,发现以下内容(http://forums.devarticles.com/microsoft-access-development-49/pass-parameters-from-vba-to-query-62367.html):

'Ed. Start - for completion of the example
dim qryStartDate as date
dim qryEndDate as date
qryStartDate = #2001-01-01# 
qryEndDate = #2010-01-01#   
'Ed. End

'QUOTEING "stallyon": To pass parameters to a query in VBA 
'                     is really quite simple:

'First we'll set some variables:
Dim qdf As Querydef
Dim rst As Recordset

'then we'll open up the query:
Set qdf = CurrentDB.QueryDefs(qryname)

'Now we'll assign values to the query using the parameters option:
qdf.Parameters(0) = qryStartDate
qdf.Parameters(1) = qryEndDate

'Now we'll convert the querydef to a recordset and run it
Set rst = qdf.OpenRecordset

'Run some code on the recordset
'Close all objects
rst.Close
qdf.Close
Set rst = Nothing
Set qdf = Nothing

(我自己没有测试过,只是在旅途中收集的东西,因为偶尔我也想这样做,但最终还是使用了我之前提到的某些把戏)

编辑 我最终有理由使用它了。这里是实际代码。

'...
Dim qdf As DAO.QueryDef
Dim prmOne As DAO.Parameter
Dim prmTwo As DAO.Parameter
Dim rst as recordset
    '...
    'open up the query:
    Set qdf = db.QueryDefs("my_two_param_query") 'params called param_one and 
                                                 'param_two

    'link your DAP.Parameters to the query
    Set prmOne = qdf.Parameters!param_one
    Set prmTwo = qdf.Parameters!param_two

    'set the values of the parameters
    prmOne = 1 
    prmTwo = 2

    Set rst = qdf.OpenRecordset(dbOpenDynaset, _
                                            dbSeeChanges)
    '... treat the recordset as normal

    'make sure you clean up after your self
    Set rst = Nothing
    Set prmOne = Nothing
    Set prmTwo = Nothing
    Set qdf = Nothing

0

这里有一个简单的方法:Microsoft 'setparameter' 信息页面

DoCmd.SetParameter "frontMthOffset", -3
DoCmd.SetParameter "endMthOffset", -2
DoCmd.OpenQuery "QryShowDifference_ValuesChangedBetweenSELECTEDMonths"

在Access查询的SQL中,包含了[frontMthOffset]实际上是在SQL中。 例如:

"select blah from mytable where dateoffset=[frontMthOffset]"

一切都只是正常工作!


0

让我们举个例子。参数化查询看起来像这样:

Select Tbl_Country.* From Tbl_Country WHERE id_Country = _
    [?enter ISO code of the country]

如果您想从表单中获取这个值([?enter ... country]),其中包含控件和一些数据,那么这可能是可行的,但需要进行一些代码规范化。

一个解决方案是将表单控件命名为某种逻辑,例如fid_Country表示将保存id_Country值的控件。然后可以将查询作为字符串:

qr = "Select Tbl_Country.* From Tbl_Country WHERE id_Country = [fid_country]"

在表单中输入所有请求的数据后,按下“查询”按钮。逻辑将浏览所有控件并检查它们是否在查询中,最终通过控件的值替换参数:

Dim ctl as Control
For each ctl in Me.controls
    If instr(qr,"[" & ctl.name & "]") > 0 Then
         qr = replace(qr,"[" & ctl.name & "]",ctl.value)
    End if
Next i

这样做,您将获得一个完全更新的查询,其中参数已被实际数据替换。根据fid_country的类型(字符串、GUID、日期等),您可能需要添加一些额外的双引号或不需要,以获得最终查询,例如:
qr = "Select Tbl_Country.* From Tbl_Country WHERE id_Country = ""GB"""

以下是一个完全兼容Access的查询语句,您可以使用它来打开记录集:

Set rsQuery = currentDb.openRecordset(qr)

我认为你已经完成了。

当你的目标是开发Access应用程序时,这个主题非常关键。你必须为用户提供一种标准的方式来查询他们GUI中的数据,不仅仅是启动查询,还要过滤连续表单(就像Excel使用其“自动筛选”选项一样)和管理报告参数。祝你好运!


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接