【问题标题】:An example of advanced database search高级数据库搜索示例
【发布时间】:2011-01-31 05:37:04
【问题描述】:

我正在寻找示例脚本。我昨天看到了一个,但为了我的一生,我今天再也找不到了。

我的任务是允许用户通过 aspx 页面上的输入控件搜索 1 个数据库表,他们可以在其中选择和,或,等于组合字段,使用 concat/stringbuilder 或类似工具即时生成 sql。 (它在公司防火墙后面运行)

请有人指出示例或教程的正确方向

我一直在处理该页面,但遇到了问题。这是Page_load;

 Protected Sub Page_Load(ByVal sender As Object, ByVal e As System.EventArgs) Handles Me.Load
    Dim sql As String = ("Select * From Table Where ")

    'variables to hold the and or values between fields
    Dim andor1v As String = AndOr1.SelectedValue.ToString()
    Dim andor2v As String = AndOr2.SelectedValue.ToString()
    Dim andor3v As String = AndOr3.SelectedValue.ToString()
    Dim andor4v As String = AndOr4.SelectedValue.ToString()
    Dim andor5v As String = AndOr5.SelectedValue.ToString()
    Dim andor6v As String = AndOr6.SelectedValue.ToString()

    'variables to stop web control inputs going direct to sql 
    Dim name As String = NameSearch.Text.ToString()
    Dim email As String = EmailSearch.Text.ToString()
    Dim city As String = CitySearchBox.Text.ToString()
    Dim province As String = ProvinceSelect.SelectedValue.ToString()
    Dim qualifications As String = QualificationsObtained.Text.ToString()
    Dim competencies As String = CompetenciesDD.SelectedValue.ToString()
    Dim expertise As String = Expertiselist.SelectedValue.ToString()

    If NameSearch.Text IsNot String.Empty Then
        sql += "Surname LIKE '%" & name & "%' "
    End If

    If EmailSearch.Text IsNot String.Empty Then
        sql += andor1v & " Email LIKE '%" & email & "%' "
    End If

    If CitySearchBox.Text IsNot String.Empty Then
        sql += andor2v & " City LIKE '%" & city & "%' "
    End If

    If QualificationsObtained.Text IsNot String.Empty Then
        sql += andor3v & " (institutionquals1 LIKE '%" & qualifications & "%') OR " & _
        "(institutionquals2 LIKE '%" & qualifications & "%') OR " & _
        "(institutionquals3 LIKE '%" & qualifications & "%') OR " & _
        "(institutionquals4 LIKE '%" & qualifications & "%') "
    End If

    Dim selectedrow As String = CompetenciesDD.SelectedValue.ToString
    Dim selectedquals As String = NQFlevel.SelectedValue.ToString
    If CompetenciesDD.SelectedValue.ToString IsNot "0" And selectedquals = 0 Then
        sql += (selectedrow & " = 1 ")

    ElseIf selectedrow = "assessortrue" And selectedquals IsNot "0" Then
        sql += andor4v & (" assessortrue=1  and assessorlvl=" & selectedquals)
    ElseIf selectedrow = "coordinatortrue" And selectedquals IsNot "0" Then
        sql += andor4v & ("coordinatortrue=1 and coordinatorlvl=" & selectedquals)
    ElseIf selectedrow = "facilitatortrue" And selectedquals IsNot "0" Then
        sql += andor4v & ("facilitatortrue=1 and facilitatorlvl=" & selectedquals)
    ElseIf selectedrow = "moderatortrue" And selectedquals IsNot "0" Then
        sql += andor4v & ("moderatortrue=1 and moderatorlvl=" & selectedquals)
    ElseIf selectedrow = "productdevelopertrue" And selectedquals IsNot "0" Then
        sql += andor4v & ("productdevelopertrue=1 and productdeveloperlvl=" & selectedquals)
    ElseIf selectedrow = "projectmanagertrue" And selectedquals IsNot "0" Then
        sql += andor4v & ("projectmanagertrue=1 and projectmanagerlvl=" & selectedquals)
    End If

    Response.Write(sql)

End Sub

经过一个小时的修改,代码现在看起来和上面一样^

现在我面临的问题是,如果用户没有输入姓氏(第一个字段)的值,但输入了电子邮件(或任何后续字段)的值,则生成的 sql 有一个额外的,就像这样;

Select * From Table Where And Email LIKE '%test%' 

我也在寻找一种方法来考虑 OR 选项。你认为这应该像马丁所说的那样完成吗?整个查询是一个和或一个或而不是 2 的混合?那么我应该能够取出所有的和/或下拉菜单?

谢谢。

注意:我并不是真的在寻找关于我应该如何参数化或关于 sql 注入的 cmets。

【问题讨论】:

  • 无论您多么信任您的用户,您肯定希望将 ' 替换为 '',就好像他们搜索 O'Reilly 一样,它会崩溃。另请参阅 SQL 注入。
  • 您有什么问题?这看起来像“质量”动态 sql,但它似乎缺少一些逻辑,你能发布更多代码吗?
  • @andrewWin 。已发布完整代码和有关问题的更多信息,谢谢。
  • 关于用户未选择选项的问题,为什么不删除“请选择”并将其默认为“和”?

标签: asp.net database vb.net search


【解决方案1】:

关于用户未选择选项的问题,您可以删除“请选择”并将其默认为“和”

如果他们选择 AND 和 OR 的混合,那么他们期望的行为是什么?

默认情况下,在没有任何括号的情况下,AND 将首先被评估

http://msdn.microsoft.com/en-us/library/ms186992.aspx

所以如果他们进入

name="Fred" 或 email="blah" 和 city="london" 和 Province="xyz" 或 资格=“学位”

我不太确定所需的语义是什么?

是吗

(name="Fred" 或 email="blah") 和 city="london" 和 (province="xyz" 或 资格=“学位”)

(name="Fred" 或 (email="blah" 和 city="london") 和 Province="xyz") 或 资格=“学位”

还是有什么不同?也许您应该将它们限制为整个查询的 AND 或 OR,或者允许它们通过键入带括号的高级搜索语法或提供查询构建器 UI 来消除歧义。

【讨论】:

  • 我想我必须在选择 or 时连接括号。所以每个都被单独评估。
  • @Martin Re:我不太确定想要的语义是什么?该死的好问题。我觉得我应该和项目负责人谈谈!
【解决方案2】:

为了避免 sql 注入并允许动态搜索,我可能会编写一个类似这样的存储过程。如果未选择任何内容,则将 ado.net 参数集合中的 DBNull.Value 作为参数值发送。使用这种方法,您可以检查所需的任何列,如果用户未选择它们,它们将被忽略。

编辑:我刚刚看到您不允许使用存储过程。我在下面更改了答案以显示参数化的 sql 语句

SELECT * FROM TABLE
WHERE ([name] = @name OR @name IS NULL)
AND (email = @email OR @email IS NULL)
AND (city = @city OR @city IS NULL)
AND (province = @province OR @province IS NULL)
AND (qualifications = @qualifications OR @qualifications IS NULL)
AND (competencies = @competencies OR @competencies IS NULL)
AND (expertise = @expertise OR @expertise IS NULL)

【讨论】:

  • 您好乔恩,非常感谢您的帮助。我认为我的项目的第 2 阶段将是在使用 concat 方法进行工作演示后进行参数化,因此我会牢记这一点。
【解决方案3】:

连接字符串来构建查询绝不是一个好主意。您应该使用存储过程或参数化查询

【讨论】:

  • 此项目不允许存储过程(老板订单)。它在防火墙内运行,针对 AD 进行身份验证,在管理区域内。我不确定我是否可以在这种情况下使用参数,尤其是在提供动态行名时。
  • 我强烈反对将这种代码放入 proc 中。 TSQL 和具有石器时代的字符串操作和测试能力。典型的动态 sql 搜索查询实际上是代码生成的一种形式,如果您将该代码放入无法进行单元测试的环境中,并且意图在转义代码的海洋中迷失(有时 TSQL 需要五个、六个或更多连续引用以逃避常见情况!)。由于代码非常难以阅读,我从来没有发现一个 TSQL 搜索过程中没有充斥着 SQL 注入机会。
【解决方案4】:

我在经典的asp上做了这个“动态”类型的查询界面。

我给你的建议是你试图在一页加载中完成整个查询,所以......

希望通过“向导”类型的界面“构建”查询 - 可以使用 ajax 来表示新意,也可以使用简单的多个页面来构建查询的每个部分。

这是本质上通过您对查询的每个部分拥有的任何方式(会话、dbstore、cookie 等)为您提供“持久性”,并且您可以在构建时检查查询的每个部分。

【讨论】:

    【解决方案5】:
     Dim sql As String = ("Select * From Table Where **1=1**")
    
        'variables to hold the and or values between fields
        Dim andor1v As String = AndOr1.SelectedValue.ToString()
        Dim andor2v As String = AndOr2.SelectedValue.ToString()
        Dim andor3v As String = AndOr3.SelectedValue.ToString()
        Dim andor4v As String = AndOr4.SelectedValue.ToString()
        Dim andor5v As String = AndOr5.SelectedValue.ToString()
        Dim andor6v As String = AndOr6.SelectedValue.ToString()
    
        'variables to stop web control inputs going direct to sql 
        Dim name As String = NameSearch.Text.ToString()
        Dim email As String = EmailSearch.Text.ToString()
        Dim city As String = CitySearchBox.Text.ToString()
        Dim province As String = ProvinceSelect.SelectedValue.ToString()
        Dim qualifications As String = QualificationsObtained.Text.ToString()
        Dim competencies As String = CompetenciesDD.SelectedValue.ToString()
        Dim expertise As String = Expertiselist.SelectedValue.ToString()
    
        If NameSearch.Text IsNot String.Empty And andor1v IsNot "0" Then
            sql += "**and** Surname LIKE '%" & name & "%' " 
        ElseIf NameSearch.Text IsNot String.Empty And andor1v Is "0" Then
            sql += "**or** Surname LIKE '%" & name & "%' "
        End If
    
      ....additional logic here.....
        Response.Write(sql)
    
    End Sub
    

    注意**部分。 1=1 在大多数 DBMS 上评估为真。这使您可以开始将您的 or / ands 连接到它上,而不必担心 () 的

    【讨论】:

      猜你喜欢
      • 2018-05-12
      • 2020-07-25
      • 2017-12-26
      • 1970-01-01
      • 2011-12-25
      • 2017-12-07
      • 2012-07-14
      • 1970-01-01
      • 2011-05-12
      相关资源
      最近更新 更多