在ms sql server上全文搜索时如何处理用户输入?

时间:2009-01-12 11:14:02

标签: sql-server full-text-search user-input

我在ms sql server上有一个简单的搜索机制,它使用全文“contains”。 我将搜索值作为参数传递给包含谓词 - 直接来自用户的输入(通过asp.net网站)。问题是我在各种情况下得到sql异常: - 当用户输入两个单词时,例如'simple case' - 当用户将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'附近的语法错误。”问题是我希望允许用户使用'*','或'和'和'条件进行高级查询。

您如何处理用户输入? 你有价值吗?

3 个答案:

答案 0 :(得分:2)

在我们的应用程序中,我们使用自己的简单查询语言作为用户输入:只有操作数(带有可选通配符的单词或短语),运算符(AND,OR,NOT)和括号。

我们解析用户输入,将其分解为组成部分并检查语法等。

如果我们对输入有效感到高兴,我们会将其重建为等效的CONTAINS条件,并将其作为参数发送到我们的搜索参数。因为我们自己创造条件,所以知道它在语法上是正确的。

如果用户输入无效,那么我们就可以向用户返回有意义的错误消息,而无需连接到数据库。

答案 1 :(得分:2)

我几年前用这个建立了一个应用程序;我所做的是前端为您提供了一个文本框来输入您的条款,它有一个下拉菜单可以选择以下几个选项:

<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>

所以我不希望他们打字或打字 - 我为他们这样做。我让他们引用一个子短语。

以下是完成此操作的一些代码。生成的短语作为参数发送到过程;作为上面提到的评论者,你真的必须这样做以防止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

答案 2 :(得分:0)

通过你得到的错误,我会说你没有使用参数进行查询。这非常危险,允许用户执行sql注入。

现在,至于您的问题,我认为最好的选择是为您设置2个文本输入类型,一个用于普通用户,另一个用于高级用户,这样您就可以知道在哪里解析高级查询。