繁体   English   中英

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

[英]How do you create a parameterized query in MS Access 2003 and use other queries/forms to fill the parameters and obtain a resultset

我希望能够在MS Access 2003中创建参数化查询,并将某些表单元素的值提供给该查询,然后返回相应的结果集并使用它们进行一些基本计算。 我想知道如何通过表单元素填充查询的参数。 如果我必须使用VBA,那很好。

对表单上的控件的引用可以直接在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子句。

这是一段代码。 它使用参数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. 将参数命名为切割器,以便在运行查询时提示用户输入值。
  2. 表单上的引用字段(可能隐藏)
  3. 动态构建查询,不要使用参数。

我认为你只需注入类似[?enter ISO code of the country]或引用表格中的字段,如: [Forms]![MyForm]![LastName]

这意味着我们不能在多个地方重复使用相同的查询,不同的字段提供数据,或者必须依赖用户在运行查询时不会弄乱数据条目。 我记得,用户输入的参数可能很难多次使用相同的值。

通常我选择了最后一个选项来动态构建查询,并根据需要更新查询对象。 然而,这很容易发生SQL注入攻击(意外或故意了解我的用户),而且它只是icky。

所以我做了一些挖掘,我在这里找到了以下内容( 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

(我自己没有测试过,只是我在旅途中收集到的东西,因为每隔一段时间我就会想要这样做,但最后使用了我之前提到的一个kludges)

编辑我终于有理由使用它。 这是实际的代码。

'...
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

简单的方法是微软'setparameter'信息页面

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

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

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

一切正常!

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

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

并且您希望能够从表单中获取此值([?enter ... country]),其中包含控件和一些数据。 嗯......这可能是可能的,但它需要一些代码规范化。

一种解决方案是让您的表单控件以某个逻辑命名,例如fid_Country用于将保存id_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使用“自动过滤”选项一样)并管理报表参数。 祝好运!

暂无
暂无

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

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