关于SQL Server 2008全文搜索的问题

时间:2009-08-31 17:38:12

标签: c# .net sql sql-server full-text-search

我已经构建了一个这样的T-SQL查询:

DECLARE @search nvarchar(1000) = 'FORMSOF(INFLECTIONAL,hills) AND FORMSOF(INFLECTIONAL,print) AND FORMSOF(INFLECTIONAL,emergency)'

SELECT * FROM Tickets
WHERE ID IN (
                -- unioned subqueries using CONTAINSTABLE
                            ...
            )

此搜索的GUI将是一个带有单个文本框的aspx页面,用户可以在其中进行搜索。

我打算以某种方式构建搜索词,就像上面的例子一样(@search)。

但我有些担忧:

  • 示例搜索字词是否包含搜索中所有字词的变化的最佳或唯一方式?
  • 我应该分开单词并在C#或T-SQL中构建搜索词。我倾向于倾向于C#进行决策/循环/构建,但我想要你的意见。
  • 由于注入风险,我讨厌动态构建SQL。我怎能防范这个?
  • 我应该使用FREETEXTTABLE吗?有没有办法让FREETEXT找到所有单词而不是任何单词?
  • 一般来说,你会怎么做呢?

4 个答案:

答案 0 :(得分:3)

我最近使用全文搜索,所以我会尝试回答你的一些问题。

•“我讨厌因为注入风险而动态构建sql。我怎样才能防范这种情况?”

我使用了这样的消毒方法:

static string SanitizeInput(string searchPhrase)
    {
        if (searchPhrase.Length > 200)
            searchPhrase = searchPhrase.Substring(0, 200);

        searchPhrase = searchPhrase.Replace(";", " ");
        searchPhrase = searchPhrase.Replace("'", " ");
        searchPhrase = searchPhrase.Replace("--", " ");
        searchPhrase = searchPhrase.Replace("/*", " ");
        searchPhrase = searchPhrase.Replace("*/", " ");
        searchPhrase = searchPhrase.Replace("xp_", " ");

        return searchPhrase;
    }

•我应该使用FREETEXTTABLE吗?有没有办法让FREETEXT查找所有单词而不是任何单词?

我确实使用过FREETEXTTABLE,但我需要任何一个词。尽管我已经读过它(我已经阅读了很多),你必须使用CONTAINSTABLE来搜索所有单词或不同的组合。 FREETEXTTABLE似乎是更轻松的解决方案,但是当你想要更深层次的自定义时,它不是一个可以选择的解决方案。

答案 1 :(得分:2)

丹,我喜欢你的SanitizeInput方法。我重构它使它更紧凑,并提高性能。

 static string SanitizeInput(string searchPhrase, int maxLength)
        {
            Regex r = new Regex(@";|'|--|xp_|/\*|\*/", RegexOptions.Compiled);
            return r.Replace(searchPhrase.Substring(0, searchPhrase.Length > maxLength ? maxLength : searchPhrase.Length), " ");
        }

        static string SanitizeInput(string searchPhrase)
        {
            const int MAX_SEARCH_PHRASE_LENGTH = 200;
            return SanitizeInput(searchPhrase, MAX_SEARCH_PHRASE_LENGTH);
        }

我同意FreeTextTable的解决方案太轻了。

答案 2 :(得分:0)

在您的示例中,您已经定义了@search变量。根据经验,由于存在注入风险,因此不应将动态连接文本包含在原始SQL中。但是,您当然可以在应用程序的调用命令对象中设置@search的值。这完全抵消了注射攻击的风险。

我建议在C#中构建搜索词;将最终搜索词作为参数传递给已经提到的。

据我记忆,FREETEXTTABLE使用断字符将搜索词完全分解为各自的组成部分。 但是,FREETEXTTABLE运算符也会自动将单词分解为屈折等值,因此如果您决定使用它,则不必构造复杂的CONTAINSTABLE运算符。

您可以INNER JOIN多个FREETEXTTABLE查询的结果来生成等效的AND结果。

答案 3 :(得分:0)

我们所有的搜索都在数据库中具有预定义有效字符的列上。 我们的搜索算法将其与仅允许这些预定义字符的正则表达式相结合。因为在搜索字符串中的这种转义不是必需的。我们的正则表达式消除了Web代码中的任何注入尝试(asp& aspx)。对于来自用户的标准注释,我们使用转义来更改在SQL,ASP,ASPX和&amp ;;中可能用于损害的所有字符。的JavaScript。
TransStar网站http://latranstar.tann.com/正在使用扩展形式的Soundex来搜索南加州任何地方的街道名称,地址和城市。 Soundex本身消除了对反注入代码的任何需求,因为它只对字母字符进行操作。