如何在MS Access 2003中创建参数化查询,以及如何使用其他查询/表单来填充参数并获取结果集
我希望能够在MS Access 2003中创建参数化查询,并将某些表单元素的值提供给该查询,然后获取对应的结果集并对其进行一些基本计算。我正在弄清楚如何获取要由表单元素填充的查询参数。如果我必须使用VBA,那很好。
解决方案
这是一段代码。它使用参数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] )
让我们举个例子。参数化查询如下所示:
Select Tbl_Country.* From Tbl_Country WHERE id_Country = _ [?enter ISO code of the country]
并且我们希望能够从表单中获得此值([?enter…country]一个),在其中我们可以拥有控件和一些数据。好吧...这可能是可行的,但是需要一些代码规范化。
一种解决方案是让表单控件以某种逻辑命名,例如将拥有" id_Country"值的控件的" fid_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使用" autofilter"选项进行处理的方式一样)并管理报表参数。祝你好运!
有三种传统方法可以解决此问题:
- 将参数命名为cleaver,以便在运行查询时提示用户输入值。
- 表单上的参考字段(可能是隐藏的)
- 快速生成查询,并且不使用参数。
我认为对我们来说必须注入[?输入国家的ISO代码]之类的内容,或者对表单上的字段进行引用,例如:[[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
尽管将它们定义为参数很重要,但是可以直接在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];
但是,我想问为什么我们需要为此保存一个查询。我们如何处理结果?以表格或者报告的形式显示它们?如果是这样,我们可以在表单/报表的记录源中执行此操作,并使保存的查询不受参数的影响,因此可以在其他上下文中使用它,而无需弹出提示填写参数。
另一方面,如果我们正在用代码做某事,则只需动态编写SQL,然后使用表单控件的文字值构造WHERE子句即可。