2

我在 ms sql server 上有一个简单的搜索机制,它使用全文“包含”。我将搜索值作为参数传递给包含谓词 - 直接来自用户的输入(通过 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 值吗?

4

3 回答 3

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>

所以我不希望他们输入 ands 或 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
于 2009-02-05T15:35:44.807 回答
2

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

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

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

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

于 2009-02-02T01:20:52.040 回答
0

根据您遇到的错误,我会说您没有使用查询参数。这是非常危险的,并且允许您的用户执行 sql 注入。

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

于 2009-01-12T11:20:26.280 回答