我在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'附近的语法错误。”问题是我希望允许用户使用'*','或'和'和'条件进行高级查询。
您如何处理用户输入? 你有价值吗?
答案 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个文本输入类型,一个用于普通用户,另一个用于高级用户,这样您就可以知道在哪里解析高级查询。