Построение хорошего поискового запроса с использованием system.data.oracleclient
Я строю функцию поиска в классе, который будет использоваться несколькими нашими страницами asp. Идея проста, взять поисковый запрос от пользователя и запросить базу данных для элемента. В настоящее время я делаю это неправильным образом, который уязвим для атак с использованием SQL-инъекций (и ELMAH там, чтобы спасти день, если что-то пойдет не так):
Public Shared Function SearchByName(ByVal searchterm As String) As DataTable
SearchByName = New DataTable
Dim con As New OracleConnection(System.Configuration.ConfigurationManager.ConnectionStrings("OracleDB").ConnectionString)
Try
con.Open()
Dim SqlStr As String = "select ID_ELEMENT, ELEMENT_NAME from table_of_elements where upper(ELEMENT_NAME) like upper('%" & searchterm & "%')"
Dim cmd As New OracleCommand(SqlStr, con)
SearchByName.Load(cmd.ExecuteReader)
Catch ex As Exception
Elmah.ErrorSignal.FromCurrentContext().Raise(ex)
End Try
con.Close()
con.Dispose()
Return SearchByName
End Function
Конкатенация строк ПЛОХА. Следующее, что вы знаете, Бобби Таблиц разрушает мою систему. Теперь правильный способ сделать это - создать правильную переменную oracle, поместив в строку строку:searchterm и добавив следующую строку:
cmd.Parameters.Add(New OracleParameter("SEARCHTERM", searchterm))
Проблема в том, что я использую оператор like, мне нужно иметь возможность иметь% по обе стороны от поискового слова, и я не могу сделать это с помощью "%:searchterm%", он просто выдает ошибку ORA-01036: недопустимое имя / номер переменной.
Могу ли я параметризировать, но при этом иметь ли мое гибкое подобное утверждение?
2 ответа
Вместо того чтобы выполнять конкатенацию в своем коде VB, выполните конкатенацию в операторе SQL. Тогда то, что вы пытаетесь сделать, должно работать. Вот несколько SQL, иллюстрирующих то, о чем я говорю:
select ID_ELEMENT, ELEMENT_NAME
from table_of_elements
where upper(ELEMENT_NAME) like ('%' || upper(:searchterm) || '%')
Кстати, у вас могут получиться более эффективные запросы, если вы переключите коллаж в ELEMENT_NAME на регистр без учета регистра, а затем удалите вызовы upper().
Поскольку вы используете Oracle, другой вариант будет использовать Oracle Text для выполнения поиска.
Для правильной настройки может потребоваться некоторое время, но если у вас есть большой объем текста для поиска или какие-то структурированные данные, он может предложить вам гораздо больше вариантов, чем простое сравнение с подстановочными знаками.
Он также имеет несколько полезных функций для работы с несколькими языками, если у вас возникла такая проблема.