Как вы обрабатываете пользовательский ввод во время полнотекстового поиска на сервере MS SQL? - PullRequest
2 голосов
/ 12 января 2009

У меня есть простой механизм поиска на сервере MS SQL, который использует полнотекстовый «содержит». Я передаю поисковое значение в качестве параметра, содержащего предикат - непосредственно из пользовательского ввода (через веб-сайт asp.net). Проблема в том, что я получаю исключение sql в различных случаях: - когда пользователь вводит два слова, например «простой случай» - когда пользователь добавляет qoute к поисковому значению, например, 'test' '

Я сделал тест, используя запрос, как показано ниже:

declare @val nvarchar(40)
set @val = N'test"' -- or 'simple case'

select x.* FROM xx as x
where CONTAINS(x.[name], @val)

Обычно я получаю: «Синтаксическая ошибка рядом с« xxx »в условии полнотекстового поиска« xxx ».» Проблема в том, что я хотел бы позволить пользователям делать расширенные запросы с условиями «*», «или» и «и».

Как вы обрабатываете пользовательский ввод? Вы значение Qoutename?

Ответы [ 3 ]

2 голосов
/ 02 февраля 2009

В нашем приложении мы используем собственный простой язык запросов для ввода пользователя: просто операнды (слова или фразы с необязательными подстановочными знаками), операторы (AND, OR, NOT) и круглые скобки.

Мы анализируем пользовательский ввод, разбиваем его на составные части и проверяем синтаксис и т. Д.

Если мы рады, что ввод действителен, мы перестраиваем его в эквивалентное CONTAINS условие и отправляем его в качестве параметра нашему поисковому запросу. Поскольку мы сами создаем условие, мы знаем , что это синтаксически правильно.

Если введенные пользователем данные недействительны, мы можем вернуть пользователю значимое сообщение об ошибке, не подключаясь к базе данных вообще.

2 голосов
/ 05 февраля 2009

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

<option selected value="AND">All of the words entered</option>
<option value="OR">Any of the words entered</option>
<option value="ALL">The exact phrase entered</option>

Так что я не хочу, чтобы они печатали ands or ors - я делаю это для них. Я позволю им цитировать подфразу.

Ниже приведен код, который выполняет это. Результирующая фраза отправляется в качестве параметра в процедуру; как упоминалось выше, вы действительно должны сделать это для защиты от внедрения SQL. К сожалению, этот код является устаревшим ASP VBScript и даже не написан хорошо по стандартам этого языка, но, возможно, это дает вам представление.

 function formatContainsString (sCriteria, sANDorOR)
    dim sReturnBuf 'where we build our string
    dim sWordList 'sCriteria split
    dim lCurPos      'where we are at in sWordList
    dim bInnerQuotes ' an open quote was found
    if sCriteria = "" or sANDorOR = "" then
        formatContainsString = ""
        exit function
    end if

    ' If the passed parameter is 'ALL' then use the exact phrase typed by users
    if sANDorOR = "ALL"  then
        formatContainsString = "'"  & chr(34) & sCriteria  & chr(34) & "'"
        Exit Function
    End If

    sReturnBuf = "'"
    sWordList = split(sCriteria," ")
    for lCurPos = 0 to ubound(sWordList)
        if bInnerQuotes then 'want to pass this as a single phrase
            sReturnBuf = sReturnBuf & " " & sWordList(lCurPos)
            if right(sWordList(lCurPos),1) = chr(34) then
               sReturnBuf = left(sReturnBuf,len(sReturnBuf)-1) & "*" & chr(34)
                sReturnBuf = sReturnBuf & " " & sANDorOR & " "'phrase is over
                bInnerQuotes = False
            end if
        else        
            if left(sWordList(lCurPos),1) = chr(34) then 
                sReturnBuf = sReturnBuf & sWordList(lCurPos)
                bInnerQuotes = True
            else
                sReturnBuf = sReturnBuf & chr(34) & sWordList(lCurPos) & "*" & _ 
                    chr(34) & " " & sANDorOR & " "'quote the word
            end if
        end if
    next
    'finally, remove the last AND or OR... and append the tick
    formatContainsString = left(sReturnBuf,len(sReturnBuf)-(len(sANDorOR)+1)) _ 
        & "'"

end function
0 голосов
/ 12 января 2009

По ошибкам, которые вы получаете, я бы сказал, что вы не используете параметры для ваших запросов. Это очень опасно и позволяет вашим пользователям выполнять инъекции sql.

Теперь, что касается вашего вопроса, я думаю, что лучшим вариантом было бы для вас установить 2 типа ввода текста, один для обычных пользователей, другой для опытных пользователей, чтобы вы могли знать, где анализировать для сложных запросов.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...