有没有一种在MS Access中创建动态,基于表单的查询的首选方法?

时间:2013-04-04 16:25:19

标签: sql database ms-access access-vba

关于我正在构建的数据库的方法的一般问题。我计划有一些表单允许DB业务用户输入条件,通过单选按钮限制他们的搜索等,然后根据他们的选择运行查询。

对于简单查询,只有一个或两个过滤器,将数据字段的条件与查询设计视图中的相应表单元素相关联似乎很容易,但这种方法失败(并且似乎很难读取/编辑)处理嵌套的if语句(例如,如果A然后是x,如果是B则是y,如果是C然后是z,那么还有q)。

我遇到了一篇文章,描述了在DB中创建一个单独的表,其中一个表存储查询名称和相应的SQL字符串,这些字符串是在onClick事件之后运行的VBA中创建的,或者是基于表单的触发器。确定查询条件的逻辑全部在VBA中,一旦代码执行,系统就会留下一个干净的SQL语句,该语句存储在上述表中,然后用于执行查询。我相信每次访问/修改表单并请求查询时,表中的SQL字符串都会被覆盖。

由于这是我所做的第一个严肃的数据库,我正在寻找有关采取方法的一些指导。我刚刚描述的是正确的还是一种相当标准/常用的方法来处理这种情况?有什么主要问题吗?如果两个数据库用户同时尝试使用不同的标准运行相同的查询,会立即跳到脑海中的那个是什么?应该注意的是,我的用户群很小 - 可能只有5个用户只能传递数据,用于临时报告等。

提前致谢!

Edit: Here's the forum post that I was referring to re: SQL strings in a separate table

编辑2:作为一般例子,假设我的数据库有一个表格如下:

  

ID ...... ...... SALE_DATE分类

     
     

1 ....... 1/1/2013 ........ Foo
  2 ....... 2013年3月3日........酒吧
  3 ....... 2013年1月1日........酒吧
  4 ....... 1/7/2013 ........酒吧

现在在我的表单上,我有一个文本框,用户可以在其中指定日期范围,并在查询中过滤

  

在[Forms]之间![myFrm]![FromDate]和[Forms]![myFrm]![ToDate]

效果很好。

至于类别,我想要复选框或其他表单元素,用户可以在其中指定包含/排除的类别。这是我遇到问题的地方。我试过了:

  

IIf([Forms]![myFrm]![Cat] = 1,([tbl_data]。[Category])In(“Foo”,“Bar”),IIf([Forms]![myFrm]![猫] = 2, “富”, “酒吧”))

... Cat = 1代表'All',2和3分别代表Foo和Bar。 Access给出了一个错误,即查询过于复杂,但是如果我删除嵌套的if(因此忽略搜索两个类别的选项),它就可以工作。

现在,显然这是一个非常简化的示例,但它让我思考如何处理表单驱动的查询,因为数据库的增长和更多的固定查询被烘焙.VBA的想法是代码将运行,评估表单数据,然后将SQL构造为

  

SELECT ...
  FROM ...
  在哪里(“Foo”,“Bar”)

希望这有助于澄清一些事情。请原谅我的无知......随着我的进展,我仍然在学习很多这方面的知识。感谢。

4 个答案:

答案 0 :(得分:3)

关于你问题中的这一点......

“如果两个数据库用户同时尝试使用不同的标准运行相同的查询,会发生什么?”

在多用户Access应用程序中,您应该将db拆分为前端和后端db文件。 BE数据库应包含表,索引和关系。 FE db应该包括您的查询,表单,报告等(基本上是您的应用程序除表之外所需的一切)和BE表的链接。

将BE db文件放在所有应用程序用户都可访问的网络共享上。每个用户都应该收到自己的FE db副本。

在这种情况下,每个用户都可以创建并运行自己的自定义即席查询,而无需踩踏其他用户的查询。

如果您需要在某处存储查询条件或整个SQL语句,可以将它们存储在FE中的本地表中,或者将它们存储在公共BE表中,但是包含一个字段,可能是用户ID,以便每个用户的查询可以单独存放。

请注意,如果您决定在本地为每个FE用户存储,则在您需要部署新的FE版本时,他们保存的设置可能会被丢弃。在这种情况下,更好的方法是为每个用户提供一个辅助db文件,以便他们可以存储自定义设置。然后,当您部署新的FE版本时,您将能够保留其设置。

我发现很难处理你问题的“大局”。但我认为您应该在拆分应用程序的上下文中考虑它。

对于一般的“搜索表单”建议,请参阅Allen Browne的详细示例中可以重复使用的内容:Search criteria


我可能会使用一种简单的方法。

为搜索结果创建单独的表单。基于该查询的表单,其中包含您要显示的所有字段。如果您在该查询中需要WHERE子句,请将其限制为仅适用于所有搜索变体的条件......也许Active = True。如果您无法确定适用于所有搜索的任何条件,请不要包含WHERE条款。

然后在搜索表单中,根据“立即搜索”命令按钮的单击事件评估用户的搜索条件。构建一个WHERE字符串,不带WHERE,并将其用作DoCmd.OpenForm WhereCondition 选项。

If Not IsNull(Me.txtStartDate) Then
    strWhere = strWhere = " AND date_field >=" & _
        Format(Me.txtStartDate, "\#yyyy-m-d\#")
End If
If Not IsNull(Me.txtCategory) Then
    strWhere = strWhere = " AND category =" & Me.txtCategory
End If
If Len(strWhere) > 0 Then
    strWhere = Mid(strWhere, 6) ' discard leading " AND "
    DoCmd.OpenForm "frmSearchResults", WhereCondition:=strWhere
Else
    MsgBox "nothing to search for"
End If

如果其中一个搜索条件是来自一组选项的一个或多个项目,则将它们显示为多选列表框并循环遍历列表框的.ItemsSelected属性以构建字符串,例如{{ 1}}。如果您遇到问题,请发布一个新问题,然后我们就可以解决这个问题。

检查我之前联系过的Allen Browne的例子。我记得,他使用过类似的技巧。

答案 1 :(得分:0)

您好我认为您可以使用链接表将数据与用户分开,这样您就不必担心当多个人同时使用数据库时会发生什么。

至于研究,我使用类似的东西。

Set MyDatabase = CurrentDb
strQuote = Chr$(34)
Set MyQuery = MyDatabase.QueryDefs("YourQuery")
I = 0

SQL_String = "SELECT T_Project.YourID, T_Project.Project_Title " & _
             "FROM (T_Project LEFT JOIN T_Groupe ON T_Project.Code_Group = T_Groupe.Code_Group) LEFT JOIN T__Contact ON T_Project.Code_Employee = T__Contact.Code_Contact "

If Not IsNull(Me.R_YourID) Then
    MyCriteria(I, 0) = " YourID "
    MyCriteria(I, 1) = Me.R_YourID
    MyCriteria(I, 2) = "="
    I = I + 1
End If

If Not IsNull(Me.R_Project_Title) Then
    MyCriteria(I, 0) = " Project_Title "
    MyCriteria(I, 1) = " " & strQuote & "*" & Me.R_Project_Title & "*" & strQuote
    MyCriteria(I, 2) = "like"
    I = I + 1
End If

If I <> 0 Then
    SQL_String = SQL_String & " Where " & MyCriteria(0, 0) & MyCriteria(0, 2) & MyCriteria(0, 1)
    j = 1
    Do While j <> I
        SQL_String = SQL_String & " and " & MyCriteria(j, 0) & MyCriteria(j, 2) & MyCriteria(j, 1)
        j = j + 1
    Loop
End If

MyQuery.SQL = SQL_String & " ORDER BY T_Project.YourID " 

Refresh
Forms![Menu_Principal]![List_Project].Requery

希望这可以帮到你

答案 2 :(得分:0)

微软有一个官方的答案:http://support.microsoft.com/kb/304302

基本上它取决于在查询中第一个过滤条件之前只需要“where”这个词。如果使用后续过滤条件,则都将以“和”一词开头。从那里,您可以根据上面的MS KB文章动态构建带有VBA的SQL查询字符串。

答案 3 :(得分:0)

请记住,这就是Access已经存在并且已经执行的操作:如果您选择“按表单过滤”,它会抛出一个表单来帮助您为查询或表单构建过滤器,它可以帮助您自动构建报表

因此,您需要确定与正在构建的不同 的内容,而不是Access所提供的内容。

通常,这意味着您要过滤报告,并且您将通过仅提供有限的选项来简化过滤。

您需要考虑第一个标准。鉴于您筛选查询和表单,并且您可以自动生成报告,您的用户可能只需要指向MS Access中已存在的功能。

由于过滤报告是常见请求,因此您可以使用现有代码:OpenGate是商业报告构建器的一个示例:谷歌并查看其他内容,包括您可以找到的免费和演示软件。

如果你想制作自己的过滤器构建器,请参考以下提示:

1)不要使用表单引用。如果我遇到特殊过滤器构建器的麻烦,我会将实际数据值构建到sql中,避免出现问题。当您不希望特殊过滤器构建器表单的复杂性时,您对表单上的字段的引用就会被使用。

2)您可以将表单用作报告。只需将背景设为白色,然后使布局看起来像一个报告。这会给你一份可过滤的报告。它与报告的工作方式完全不同:有时这是一个优势。

3)大多数人不想玩过滤器。他们想要一个特定的查询/报告设置,并保存,然后他们只是每天/每周/每月/每年运行。

4)如果用户想要提取特定数据点,他们可能不需要让它看起来与更大报告中的单行完全相同。不要对配置中的单选按钮感兴趣:只需提取不同版本的表单/查询/报告。