【问题标题】:Returning records that partially match a value返回部分匹配值的记录
【发布时间】:2010-09-18 10:15:06
【问题描述】:

我正在尝试使查询工作,该查询从表单控件中获取值(有时只是字符串的第一部分)。我遇到的问题是它只在输入完整字符串时才返回记录。

即在姓氏框中,我应该可以输入 gr,它会弹出

绿色 灰色的 格雷厄姆

但目前除非使用完整的搜索字符串,否则它不会显示任何内容。

有问题的表单上有4个搜索控件,只有在填写框的情况下才会在查询中使用。

查询是:

SELECT TabCustomers.*,
       TabCustomers.CustomerForname AS NameSearch,
       TabCustomers.CustomerSurname AS SurnameSearch,
       TabCustomers.CustomerDOB AS DOBSearch,
       TabCustomers.CustomerID AS MemberSearch
FROM TabCustomers
WHERE IIf([Forms]![FrmSearchCustomer]![SearchMember] Is Null
          ,True
          ,[Forms]![FrmSearchCustomer]![SearchMember]=[customerid])=True
      AND IIf([Forms]![FrmSearchCustomer].[SearchFore] Is Null
              ,True
              ,[Forms]![FrmSearchCustomer]![SearchFore] Like [customerforname] & "*")=True
      AND IIf([Forms]![FrmSearchCustomer]![SearchLast] Is Null
              ,True
              ,[Forms]![FrmSearchCustomer]![SearchLast] Like [customersurname] & "*")=True
      AND IIf([Forms]![FrmSearchCustomer]![Searchdate] Is Null
              ,True
              ,[Forms]![FrmSearchCustomer]![Searchdate] Like [customerDOB] & "*")=True;

【问题讨论】:

  • 我不建议将 LIKE 运算符与看起来像日期字段的内容一起使用。您可能会得到各种意想不到的结果,例如用户输入 1 表示 1 月(或 1 日)并匹配 10 月、11 月、12 月(或 10 日至 19 日)。
  • 您应该使用 application.buildCriteria 即时构建您的 WHERE 子句。这就是它所做的(我认为......)
  • BuildCriteria 是一个非常出色的工具。它是表达式服务的同一部分的编程接口,可将您在 QBE 的标准行中键入的内容解析为正确的语法。这是我最常用的非显而易见的访问命令之一。

标签: sql ms-access sql-like


【解决方案1】:

有一个访问方法!

如果您在表单上有“过滤器”控件,为什么不使用 Application.buildCriteria 方法,它允许您将过滤条件添加到字符串,然后从该字符串中进行过滤,然后即时构建您的 WHERE 子句?

selectClause = "SELECT TabCustomers.* FROM TabCustomers"
if not isnull(Forms!FrmSearchCustomer!SearchMember) then
    whereClause = whereClause & application.buildCriteria(your field name, your field type, your control value) &  " AND "
endif
if not isnull(Forms!FrmSearchCustomer!SearchFore) then
    whereClause = whereClause & application.buildCriteria(...) &  " AND "
endif
if not isnull(Forms!FrmSearchCustomer!SearchLast) then
    whereClause = whereClause & application.buildCriteria(...) &  " AND "
endif
if not isnull(Forms!FrmSearchCustomer!SearchDate) then
    whereClause = whereClause & application.buildCriteria(...) & " AND "
endif
--get rid of the last "AND"
if len(whereClause) > 0 then
     whereClause = left(whereClause,len(whereClause)-5)
     selectClause = selectClause & " WHERE " & whereClause
endif
-- your SELECT instruction is ready ...

编辑:buildCriteria 将返回(例如):

  • 'field1 = "GR"' 在控件中键入“GR”时
  • 'field1 LIKE "GR*"' 当您在控件中键入 "GR*"
  • 'field1 LIKE "GR*" or field1 like "BR*"' 如果您在控件中键入 'LIKE "GR*" OR LIKE "BR*"'

PS:如果表单上的“过滤器”控件始终具有相同的语法(比如说“search_fieldName”,其中“fieldName”对应于基础记录集中的字段)并且始终位于同一区域(假设formHeader),然后可以编写一个函数,自动为当前表单生成一个过滤器。然后可以将此过滤器设置为表单过滤器,或用于其他用途:

For each ctl in myForm.section(acHeader).controls
    if ctl.name like "search_"
        fld = myForm.recordset.fields(mid(ctl.name,8))
        if not isnull(ctl.value) then
           whereClause = whereClause & buildCriteria(fld.name ,fld.type, ctl.value) & " AND "
        endif
    endif
next ctl
if len(whereClause)> 0 then ...

【讨论】:

  • 我肯定会推荐这种方法:它更容易支持,特别是如果您在表单中添加额外的标准。我在一个包含多达 20 个条件的表单上使用了它(使用不同的统计数据组合搜索曲棍球运动员的数据库)。
  • 好点。我的回应是修复查询错误,但随着时间的推移,这是一个更好的整体解决方案。请注意,我在 BuildCriteria 中看到了有关日期处理的错误。
  • 我找到了一个辅助函数,它仅在传递非空字符串时添加“AND”才能避免最后一次扫描。 whereClause = AddAnd(whereClause...)。对于搜索,调用的额外费用可以忽略不计。
【解决方案2】:

这是一个完整的重写,以允许名称字段或出生日期字段中的空值。如果在数字 customerid 字段中输入文本,此查询不会因为过于复杂而失败。

SELECT TabCustomers.CustomerForname AS NameSearch, TabCustomers.CustomerSurname AS SurnameSearch, TabCustomers.CustomerDOB AS DOBSearch, TabCustomers.customerid AS MemberSearch
FROM TabCustomers
WHERE TabCustomers.customerid Like IIf([Forms]![FrmSearchCustomer].[Searchmember] Is Null,"*",[Forms]![FrmSearchCustomer]![Searchmember])
AND Trim(TabCustomers.CustomerForname & "") Like IIf([Forms]![FrmSearchCustomer].[SearchFore] Is Null,"*",[Forms]![FrmSearchCustomer]![SearchFore] & "*")
AND Trim(TabCustomers.CustomerSurname & "") like IIf([Forms]![FrmSearchCustomer].[Searchlast] Is Null,"*",[Forms]![FrmSearchCustomer]![SearchLast] & "*")
AND (TabCustomers.CustomerDOB Like IIf([Forms]![FrmSearchCustomer].[SearchDate] Is Null,"*",[Forms]![FrmSearchCustomer]![SearchDate] ) Or TabCustomers.CustomerDOB Is Null)

【讨论】:

    【解决方案3】:

    你的 LIKE 表达式倒过来了。我重写了查询以删除不必要的 IIF 命令并修复 LIKE 运算符的操作数顺序:

    SELECT TabCustomers.*
    FROM TabCustomers
    WHERE (Forms!FrmSearchCustomer!SearchMember Is Null Or Forms!FrmSearchCustomer!SearchMember=[customerid]) 
    And (Forms!FrmSearchCustomer.SearchFore Is Null Or [customerforname] Like Forms!FrmSearchCustomer!SearchFore & "*") 
    And (Forms!FrmSearchCustomer!SearchLast Is Null Or [customersurname] Like Forms!FrmSearchCustomer!SearchLast & "*") 
    And (Forms!FrmSearchCustomer!Searchdate Is Null Or [customerDOB] Like Forms!FrmSearchCustomer!Searchdate & "*");
    

    我通过复制最可能的情况来构建该查询:我创建了一个包含提到的字段的虚拟表,以及一个包含字段的表单和一个包含上面列出的查询的子表单,当按下搜索按钮时,会刷新。如果您愿意,我可以提供我创建的示例的下载链接。该示例按预期工作。 J 只拿起了 Jim 和 John,而 John 或 Jo 只提取了 John 的唱片。

    【讨论】:

    • 这已经在 UtterAccess 上反弹了大约 2 周,还没有接近!!!
    • 如果用户在数字字段中输入文本,此查询将因过于复杂而失败。此外,如果任何字段为空,则不会返回记录。
    • 搜索表单有一个非常强大的奇偶校验 - 所有内容都必须使用用户友好的错误消息编写,因此不应该发生......
    【解决方案4】:

    发生了两件事 - 应该颠倒比较,并且您没有正确引用字符串。

    应该是“部分字符串+通配符”之类的[数据库字段]

    所有字符串都需要用引号括起来 - 不知道为什么您的查询不会引发错误

    所以以下应该可以工作:

    ,[customerforname] Like  """" & [Forms]![FrmSearchCustomer]![SearchFore] & "*""" )=True
    

    请注意 """",它是将单个双引号附加到字符串的唯一方法。

    【讨论】:

    • 嗨 DJ,我已尝试将查询更改为您的建议,但它不想知道 - 它现在根本不返回任何记录...至于错误,我宁愿它抛出一个错误而不是表现得像它正在工作并浪费每个人的时间:(
    • 这类似于我的示例,除了显示的引号假定它是内联代码(从字符串构建的 SQL),而不是表单的记录源。我建议使用 OR 消除示例中所示的 IIF,因为我发现它比 IIF 表达式更易于阅读。
    • 好吧,通常我会动态构建一个搜索查询,所以很难知道发生了什么。可能是您的其他术语为 Null,而您实际上并不需要所有这些 IIF
    • 而不是像“部分字符串+通配符”这样的[数据库字段]我认为应该是像“部分字符串”+“通配符”这样的[数据库字段]
    • "请注意 """",这是将单个双引号附加到字符串的唯一方法。"嗯,& Chr$(39) 怎么样??
    【解决方案5】:

    我唯一的想法是可能需要一个 () 来对类似的内容进行分组

    例如第一部分的sn-p

    ,[Forms]![FrmSearchCustomer]![SearchFore] Like ([customerforname] & "*"))=True
    

    我已经有一段时间没有使用访问权限了,但这是我想到的第一件事

    【讨论】:

    • 不幸的是,米切尔没有成功,感谢您的关注:)
    • 该死!我想我会试一试,我无法访问我所有的机器,所以我无法测试
    猜你喜欢
    • 2011-09-12
    • 2021-07-06
    • 2016-03-17
    • 2012-04-20
    • 2021-05-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-12-10
    相关资源
    最近更新 更多