Пример расширенного поиска в базе данных

#asp.net #database #vb.net #search

#asp.net #База данных #vb.net #Поиск

Вопрос:

я ищу пример скрипта. Я видел один вчера, но, хоть убейте, не могу найти его сегодня снова.

Моя задача состоит в том, чтобы разрешить пользователю выполнять поиск в 1 таблице базы данных с помощью элементов управления вводом на странице aspx, где они могут выбирать и , или , equals для объединения полей, генерируя sql «на лету» с помощью concat / stringbuilder или аналогичного. (выполняется за корпоративным брандмауэром)

Пожалуйста, кто-нибудь может указать мне правильное направление примера или руководства

Я работал над страницей, но столкнулся с проблемами. Вот страница, загруженная;

  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 '%" amp; name amp; "%' "
    End If

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

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

    If QualificationsObtained.Text IsNot String.Empty Then
        sql  = andor3v amp; " (institutionquals1 LIKE '%" amp; qualifications amp; "%') OR " amp; _
        "(institutionquals2 LIKE '%" amp; qualifications amp; "%') OR " amp; _
        "(institutionquals3 LIKE '%" amp; qualifications amp; "%') OR " amp; _
        "(institutionquals4 LIKE '%" amp; qualifications amp; "%') "
    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 amp; " = 1 ")

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

    Response.Write(sql)

End Sub
  

После нескольких часов работы код теперь выглядит так, как описано выше ^

Теперь проблема, с которой я столкнулся, заключается в том, что если пользователь не вводит значение для фамилии (первое поле), но вводит значение для электронной почты (или любых последующих полей), созданный sql содержит дополнительные и, подобные этому;

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

Я также ищу способ учесть опцию ИЛИ. Как вы думаете, это следует делать так, как говорит Мартин, когда весь запрос представляет собой либо «и», либо «или», а не сочетание двух? Тогда я должен быть в состоянии удалить все выпадающие списки и / или?

Спасибо.

ПРИМЕЧАНИЕ: На самом деле я не ищу комментариев о том, как я должен параметризовать или о внедрении sql.

Комментарии:

1. Вы определенно захотите заменить «на «, независимо от того, насколько вы доверяете своим пользователям, поскольку, если они будут искать O’Reilly, это приведет к сбою. Также смотрите SQL-инъекцию.

2. с какими проблемами вы столкнулись? это выглядит как «качественный» динамический sql, но, похоже, в нем отсутствует некоторая логика, вы можете опубликовать больше кода?

3. @andrewWin . разместил полный код и дополнительную информацию о проблеме, спасибо.

4. Что касается вашей проблемы с тем, что пользователи не выбирают опцию, почему бы просто не убрать «пожалуйста, выберите» и установить по умолчанию «и»?

Ответ №1:

Что касается вашей проблемы с тем, что пользователи не выбирают опцию, вы могли бы просто удалить «пожалуйста, выберите» и установить по умолчанию «и»

Также, каково желаемое поведение, если они выбирают сочетание AND и OR?

По умолчанию ANDS будут оцениваться первыми при отсутствии каких-либо скобок

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

Поэтому, если они вводят

имя= «Фред» или электронная почта = «бла», город = «Лондон», провинция = «xyz» или квалификация = «Степень»

Я не совсем уверен, какой должна быть желаемая семантика?

Это

(имя = «Фред» или электронная почта = «бла») и город = «Лондон» и (провинция= «xyz» или квалификация=»Степень»)

или

(имя = «Фред» или (электронная почта = «бла» и город = «Лондон») и провинция = «xyz») или квалификация = «Степень»

Или что-то другое? Возможно, вам следует ограничить их И или ИЛИ для всего запроса или разрешить им устранять неоднозначность, либо введя синтаксис расширенного поиска в скобках, либо предоставив пользовательский интерфейс конструктора запросов.

Комментарии:

1. Я думаю, что я должен объединить скобки, когда выбрано или. таким образом, каждый из них оценивается отдельно.

2. @Martin Re: Я не совсем уверен, какой должна быть желаемая семантика? Чертовски хороший вопрос. Думаю, мне следует поговорить с владельцем проекта!

Ответ №2:

Чтобы избежать внедрения sql и разрешить динамический поиск, я бы, вероятно, написал хранимую процедуру примерно так. Если ничего не выбрано, отправьте DBNull.Значение в ado.net сбор параметров в качестве значения параметра. При таком подходе вы можете проверять любые столбцы, которые вы хотите, и если они не выбраны пользователем, они будут проигнорированы.

РЕДАКТИРОВАТЬ: я только что увидел, что вам не разрешено использовать хранимые процедуры. Я изменил свой ответ ниже, чтобы показать параметризованный оператор 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)
  

Комментарии:

1. Привет, Джон, большое спасибо за помощь. Я думаю, что этапом 2 моего проекта будет параметризация, как только у меня будет рабочая демонстрация с использованием метода concat, поэтому я буду иметь это в виду.

Ответ №3:

Объединение строк для построения запроса никогда не является хорошей идеей. Вам следует использовать хранимую процедуру или параметризованные запросы

Комментарии:

1. Для этого проекта не разрешено использовать хранимые процедуры (заказы боссов). Он выполняется внутри брандмауэра с авторизацией в AD, внутри области администрирования. Я не уверен, что мог бы использовать параметры для этой ситуации, особенно при предоставлении динамических имен строк.

2. Я категорически не согласен с помещением такого рода кода в proc. TSQL и the обладают возможностями обработки строк каменного века и тестирования. Типичные динамические поисковые запросы sql на самом деле представляют собой форму генерации кода, и если вы помещаете этот код в среду, где вы не можете выполнять модульное тестирование, и цель теряется в море escape-кодов (иногда TSQL требует пять, шесть или более одинарных кавычек подряд, чтобы избежать распространенных сценариев!). Я никогда не находил поисковую программу TSQL, которая не была бы переполнена возможностями SQL-инъекций из-за того, что код был настолько труден для чтения.

Ответ №4:

Я создал этот интерфейс запросов «динамического» типа на классическом asp.

Совет, который я даю вам, заключается в том, что вы пытаетесь выполнить весь запрос за одну загрузку страницы таким образом…

Посмотрите на «построение» запроса с помощью интерфейса типа «мастер» — либо ajax для новизны, либо простое создание нескольких страниц для каждой части построения запроса.

Это essence дает вам «постоянство» с помощью любых имеющихся у вас средств (session, 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 '%" amp; name amp; "%' " 
    ElseIf NameSearch.Text IsNot String.Empty And andor1v Is "0" Then
        sql  = "**or** Surname LIKE '%" amp; name amp; "%' "
    End If

  ....additional logic here.....
    Response.Write(sql)

End Sub
  

обратите внимание на ** части. В большинстве СУБД значение 1= 1 равно true. Это позволяет вам просто начать объединение ваших or / and с ним, не беспокоясь о том, что ()