SQL Server字符串操作 - 拆分搜索项并构建新字符串

时间:2011-05-10 13:10:45

标签: sql-server tsql string

我目前正在为我们的网站构建基于SQL Server全文索引的搜索功能,并且需要将用户的输入拆分为一组搜索词。一旦术语被拆分,我就需要将它们重新构建为一个字符串,其中包含将针对CONTAINS()或CONTAINSTABLE()全文查询执行的查询。

例如,如果用户输入

Jon Sidnell

进入我们的搜索框,我希望能够将该字符串转换为以下内容:

'("jon*" OR FORMSOF(THESAURUS, jon) OR FORMSOF(INFLECTIONAL, jon)) OR 
("sidnell*" OR FORMSOF(THESAURUS, sidnell) OR FORMSOF(INFLECTIONAL, sidnell))'

显然,如果用户输入中有三个单词,则会出现三组“通配符或同义词或变形”字样。

成为一名T-SQL新手(不是新手,但肯定不是大师!)我不确定最好的方法。我已经google了,虽然我遇到了有助于初始字符串拆分的事情,但我还没有真正了解如何最好地利用拆分表示来构造结果字符串。

有人可以帮忙吗?

2 个答案:

答案 0 :(得分:1)

我不知道这是否是解决问题的最有效方法,但我想到的是封装逻辑以将输入字符串拆分为表值函数。

调用函数并将结果存储到表变量中。

迭代表变量并将拆分字符串连接到您将用于搜索的最终字符串。

我没有在这里包含函数的代码(为了简洁起见),但在我的情况下,我的函数接受要拆分的字符串和用于拆分字符串的分隔符,并返回一个具有以下结构的表:{{1 }}

一旦你有了这个功能,你就可以将它包含在以下内容中:

Position INT, Value VARCHAR(8000)

输出应该如下所示:

SET NOCOUNT ON

DECLARE @sampleString VARCHAR(500)
SET @sampleString = 'Jon Sidnell Rocks'

DECLARE @delimiter VARCHAR(20);
SET @delimiter = ' '

DECLARE @SplitResults TABLE (
    POSITION INT, 
    VALUE VARCHAR(8000), 
    fUsed BIT DEFAULT 0)

INSERT INTO @SplitResults ( POSITION, VALUE )
SELECT * FROM dbo.ufn_SplitString(@sampleString, @delimiter)

--Set up a simple loop instead of having to open up a cursor
DECLARE @Value VARCHAR(8000);
DECLARE @Position INT;
SELECT @Value = q.VALUE, @Position = q.Position
FROM (SELECT TOP 1 VALUE, Position FROM @SplitResults WHERE fUsed = 0)q

DECLARE @SearchString VARCHAR(8000)
WHILE @@ROWCOUNT <> 0 AND @Value IS NOT NULL
BEGIN

    IF @Position = 1
    BEGIN
        SET @SearchString = '("' + @Value + '*" OR FORMSOF(THESAURUS, '+ @Value +') OR FORMSOF(INFLECTIONAL, ' + @Value + '))'
    END
    ELSE
    BEGIN
        SET @SearchString = @SearchString + ' OR ("' + @Value + '*" OR FORMSOF(THESAURUS, '+ @Value +') OR FORMSOF(INFLECTIONAL, ' + @Value + '))'
    END

    --Update record so we know we used it
    UPDATE @SplitResults SET fUsed = 1 
    WHERE Position = @Position AND VALUE = @Value

    --Get Next Value to Work With
    SELECT @Value = q.VALUE, @Position = q.Position
    FROM (SELECT TOP 1 VALUE, Position FROM @SplitResults WHERE fUsed = 0)q
END

PRINT @SearchString;

SET NOCOUNT OFF;

答案 1 :(得分:1)

如果您使用SQLCLR用户定义函数来拆分字符串,那么有相当不错的字符串操作方法。您可以使用以下字符串并为每个搜索词应用String.Format方法。它应该足够快,除非有非常高的音量,甚至可能。

“(\”{0} * \“或FORMSOF(THESAURUS,{0})或FORMSOF(INFLECTIONAL,{0}))”

public static SqlString convertStringToFTS(SqlString input)
{
    string[] strings = input.ToString().Split(new string[] {" "}, StringSplitOptions.RemoveEmptyEntries);

    StringBuilder sb = new StringBuilder();
    foreach (string s in strings)
    {
        if (sb.Length > 0)
        {
            sb.Append(" OR ");
        }
        else
        { 
            sb.Append ("(");
        }
        sb.Append(string.Format("(\"{0}*\" OR FORMSOF(THESAURUS, {0}) OR FORMSOF(INFLECTIONAL, {0}))", s));
    }
    sb.Append(")");
    return sb.ToString();
}

我会说可能有更有效的方法来实现这一目标。

祝你好运。我希望这会有所帮助。