相同的参数化SQL生成的SQL不返回任何结果

时间:2013-10-23 11:06:55

标签: full-text-search sql-server-2012

令人困惑的问题。我正在使用SQL全文搜索,我最初使用string.format直接执行查询来创建它们。以下是sql profiler生成的SQL字符串示例:

SELECT TOP 100 * FROM CatName WHERE CONTAINS(FullName, '"Spotty" AND "Cat"')

效果很好。

但是,由于我通过获取用户输入并将其放入来创建该字符串,因此我们存在SQL注入的风险。因此,我创建了参数化的SQL。

分析器中执行的SQL是:

exec sp_executesql N'SELECT TOP 100 * FROM CatName WHERE CONTAINS(FullName, ''"@p1" AND "@p2"'')',N'@p1 nvarchar(6),@p2 nvarchar(3)',@p1=N'Spotty',@p2=N'Cat'

据我所知,这是一样的。但是,第二个查询不返回任何结果。

我怀疑这与参数被替换的方式有关,因为全文搜索查询在每个参数的单引号内使用双引号,但我完全失去了。

我需要一种方法来清理输入以防止SQL注入,这是我在互联网上找到的全部内容。

有什么想法吗?

包含和不包含参数的代码:

string _fullTextSearchQuery = "SELECT TOP {0} * FROM {1} WHERE CONTAINS({2}, '{3}')";

var searchText = @"""" + searchText.Replace(" ", @""" AND """) + @"""";

string[] unorderedWords = searchText.Split(' ');

searchText = "";

int unorderedIndex = 1;
foreach (string word in unorderedWords)
{
    searchText += @"""" + "@p" + unorderedIndex + @""" AND ";
    parameters.Add(new SqlParameter("p" + unorderedIndex, word));
    unorderedIndex++;
}

searchText = searchText.Substring(0, searchText.Length - 5);

然后以此方式创建最终字符串:

string textSearchQuery = string.Format(
    _fullTextSearchQuery,
    top,
    tableName,
    columnName,
    searchText);

return catContext.SqlQuery<T>(textSearchQuery, parameters.ToArray());

因为它有点混乱,所以这里正好是在执行之前生成的字符串:

非参数化:

"SELECT TOP 100 * FROM CatName WHERE CONTAINS(FullName, '\"Spotty\" AND \"Cat\"')"

参数化:

"SELECT TOP 100 * FROM CatName WHERE CONTAINS(FullName, '\"@p1\" AND \"@p2\"')"

参数数组正确,没有misc。引用它就像你期望的那样。

1 个答案:

答案 0 :(得分:0)

解决这个问题非常简单,重要的是要将传递给CONTAINS的值作为单个值而不是多个值来考虑。

所以,我在“Spotty”和“Cat”中传递,并假设这是2个参数,实际上整个字符串是一个参数。

所以这是一个"SELECT TOP {0} * FROM {1} WHERE CONTAINS({2}, @P1)";

的简单案例

其中@P1 = "'\"Spotty\" AND \"Cat\"'"