【问题标题】:MS SQL - CONTAINS full-text search w/ variable number of values, not using dynamic sqlMS SQL - 包含带有可变数量值的全文搜索,不使用动态 sql
【发布时间】:2016-07-25 14:59:28
【问题描述】:

我在一个表上创建了一个全文索引列。

我有一个存储过程,我可以将变量“搜索此文本”的值传递给它。我想在全文栏中搜索“search”、“this”和“text”。要搜索的单词数量是可变的。

我可以使用类似的东西

WHERE column LIKE '%search%' OR column LIST '%this%' OR column LIKE '%text%'

但这需要我使用动态 SQL,而我正试图避免这种情况。

如何使用我的全文搜索来查找每个单词,大概使用 CONTAINS,并且不将整个存储过程转换为动态 SQL?

【问题讨论】:

  • dynamic SQL, which I'm trying to avoid --> 为什么?
  • 您可能会阅读这篇关于搜索类型查询的文章。 sqlinthewild.co.za/index.php/2009/03/19/catch-all-queries
  • @AaronBertrand - 我们的学长希望我们尽可能避免。
  • 对,但是有什么好的理由吗?根据我的经验,动态 SQL 到目前为止是使用可变数量的 where 子句解决查询的最佳方法。我称这些为“the kitchen sink”。
  • @AaronBertrand 我还在学习 SQL。可能是他暂时试图教我“最佳实践”。实际上,我正在学习很多方法来完成某些 SQL 任务,几个月前我认为这些任务只能通过动态 SQL 来完成。

标签: sql-server stored-procedures full-text-search


【解决方案1】:

如果你说你肯定启用了 SQL 表全文搜索,那么你可以使用如下查询。

select * from table where contains(columnname,'"text1" or "text2" or "text3"' )

详情见下方链接

Full-Text Indexing Workbench

【讨论】:

    【解决方案2】:

    所以我想我想出了一个解决方案。我创建了以下标量函数:

    CREATE FUNCTION [dbo].[fn_Util_CONTAINS_SearchString]
    (
        @searchString NVARCHAR(MAX),
        @delimiter NVARCHAR(1) = ' ',
        @ANDOR NVARCHAR(3) = 'AND'
    )
    RETURNS NVARCHAR(MAX)
    AS
    BEGIN
        IF @searchString IS NULL OR LTRIM(RTRIM(@searchString)) = '' RETURN NULL
    
        -- trim leading/trailing spaces
        SET @searchString = LTRIM(RTRIM(@searchString))
    
        -- remove double spaces (prevents empty search terms)
        WHILE CHARINDEX('  ', @searchString) > 0
        BEGIN
            SET @searchString = REPLACE(@searchString,'  ',' ')
        END
    
        -- reformat
        SET @searchString = REPLACE(@searchString,' ','" ' + @ANDOR + ' "') -- replace spaces with " AND " (quote) AND (quote)
        SET @searchString = ' "' + @searchString + '" ' -- surround string with quotes
    
        RETURN @searchString
    END
    

    我可以得到我的结果:

    DECLARE @ftName NVARCHAR (1024) = dbo.fn_Util_CONTAINS_SearchString('value1 value2',default,default)
    SELECT * FROM Table WHERE CONTAINS(name,@ftName)
    

    如有任何 cmets/建议,我将不胜感激。

    【讨论】:

      【解决方案3】:

      供您参考。

      我了解您的学长希望避免使用动态 SQL,但我坚信动态 SQL 不是邪恶的。

      在下面的示例中,您可以看到,只需几个参数(甚至是默认值),以及 3 行代码,您就可以:

      1) Dynamically search any source 
      2) Return desired or all elements
      3) Rank the Hit rate
      

      SQL

      Declare @SearchFor  varchar(max) ='Daily,Production,default'  -- any comma delim string
      Declare @SearchFrom varchar(150) ='OD'                        -- table or even a join statment
      Declare @SearchExpr varchar(150) ='[OD-Title]+[OD-Class]'     -- Any field or even expression
      Declare @ReturnCols varchar(150) ='[OD-Nr],[OD-Title]'        -- Any field(s) even with alias 
      
      Set @SearchFor = 'Sign(CharIndex('''+Replace(Replace(Replace(@SearchFor,' , ',','),', ',''),',',''','+@SearchExpr+'))+Sign(CharIndex(''')+''','+@SearchExpr+'))'
      Declare @SQL varchar(Max) = 'Select * from (Select Distinct'+@ReturnCols+',Hits='+@SearchFor+' From '+@SearchFrom + ') A Where Hits>0 Order by Hits Desc' 
      Exec(@SQL)
      

      返回

      OD-Nr   OD-Title                    Hits
      3       Daily Production Summary    2
      6       Default Settings            1
      

      我应该补充一点,我的搜索字符串是逗号分隔的,但你可以换成空格。

      另一个注意事项 CharIndex 可以比 LIKE 快得多。看一看 http://cc.davelozinski.com/sql/like-vs-substring-vs-leftright-vs-charindex

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 2021-12-17
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2013-07-16
        • 1970-01-01
        • 2016-12-03
        相关资源
        最近更新 更多