#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 с ним, не беспокоясь о том, что ()