0

我可以在 WHERE 子句中放置一个 WHILE 循环吗?我有一个存储过程,我试图在其中加入文本搜索功能。我让它为这样的完全匹配工作:

AND (@exactString = '' 
    OR (CHARINDEX(@exactString, [Short Description]) > 0 
        OR CHARINDEX(@exactString, [Description]) > 0
        OR CHARINDEX(@exactString, [Manufacturer]) > 0))

接下来,我尝试进行“任何单词”匹配和“所有单词”匹配。我可以使用以下 WHILE 循环获取要搜索的搜索字符串:

DECLARE @searchString varchar(max)
DECLARE @endIndex int

SET @allString = LTRIM(RTRIM(@allString))
WHILE LEN(@allString) > 0
BEGIN
    SET @endIndex = CHARINDEX(' ', @allString) > 0
    IF @endIndex > 0
    BEGIN
        SET @searchString = LEFT(@allString, @endIndex)
        SET @allString = LTRIM(RTRIM(RIGHT(@allString, @endIndex)))
    END
ELSE
    BEGIN
        SET @searchString = @allString
        SET @allString = ''
    END
END

现在我想像上面使用@exactString 一样使用@searchString 变量。有没有办法在我的循环中做到这一点,或者我是否缺少其他一些可以在这里工作的技术?

谢谢你的帮助,丹

4

2 回答 2

1

我使用表值函数通过如下查询执行此任务:

SELECT I.*
  FROM @info AS I
        INNER JOIN dbo.funcSplitToTable( ' ', @allString ) AS S
                ON I.[Manufacturer] LIKE '%' + S.result + '%'
                OR I.[Description] LIKE '%' + S.result + '%'
                OR I.[Short Description] LIKE '%' + S.result + '%'

该表值函数定义如下:

CREATE FUNCTION dbo.funcSplitToTable
/*
   Split a string into parts base on a separation character to produce
   a table that has one column containing the results of the split.

   EXAMPLE:
      SELECT * FROM dbo.funcSplitToTable( '~', 'MAINT~12221~10001~10/25/2004~CANCELLED~1' )
      SELECT * FROM dbo.funcSplitToTable( '~', '' )
      SELECT * FROM dbo.funcSplitToTable( '~', NULL )
      SELECT * FROM dbo.funcSplitToTable( NULL, 'MAINT~12221~10001~10/25/2004~CANCELLED~1' )
      SELECT * FROM dbo.funcSplitToTable( '', 'MAINT~12221~10001~10/25/2004~CANCELLED~1' )

   RETURN:
      Table with one column containing resulting strings.
*/
(
    @strSearch       AS varchar(255)            -- String to search for.
   ,@strText         AS varchar(MAX )           -- Text to search for string.
)
RETURNS @tblResult TABLE (
   result varchar(MAX) NOT NULL
)
WITH SCHEMABINDING
AS
BEGIN
   DECLARE @iLastPos    int
   DECLARE @iPos        int
   DECLARE @strResult   varchar(MAX)

   IF @strText IS NULL RETURN ;
   IF @strSearch IS NULL SET @strSearch = '' ;

   SET @strResult    = NULL ;
   SET @iLastPos     = 1 ;
   SET @iPos         = CHARINDEX( @strSearch, @strText ) ;

   WHILE @iPos > 0
   BEGIN
      IF (@iPos - @iLastPos) > 0
          INSERT INTO @tblResult
          SELECT SUBSTRING( @strText, @iLastPos, (@iPos - @iLastPos) ) AS result
          ;
      SET @iLastPos  = @iPos + 1 ;
      SET @iPos      = CHARINDEX( @strSearch, @strText, @iLastPos ) ;
   END

   IF (1 + LEN(@strText) - @iLastPos) > 0
       INSERT INTO @tblResult
       SELECT SUBSTRING( @strText, @iLastPos, (1 + LEN(@strText) - @iLastPos) ) AS result
       ;
   RETURN ;
END
于 2012-08-09T23:11:17.377 回答
0

我从 Michael Erickson 那里得到了一个很好的答案,它完全适用于“任何”搜索。对于“全部”搜索。我用整个查询建立了一个 sql 字符串。“全部”搜索部分在这里:

IF LEN(@allString) > 0
BEGIN
    DECLARE @searchString varchar(max)
    DECLARE @endIndex int
    DECLARE @isFirstString bit

    SET @isFirstString = 0
    SET @allString = LTRIM(RTRIM(@allString))
    WHILE LEN(@allString) > 0
    BEGIN
        SET @endIndex = CHARINDEX(' ', @allString)
        IF @endIndex > 0
            BEGIN
                SET @searchString = LTRIM(RTRIM(LEFT(@allString, @endIndex)))
                SET @allString = LTRIM(RTRIM(RIGHT(@allString, LEN(@allString) - @endIndex)))
            END
        ELSE
            BEGIN
                SET @searchString = @allString
                SET @allString = ''
            END
        SET @sql = @sql + ' AND ((CHARINDEX(''' + cast(@searchString as varchar(max)) + ''', [Short Description]) > 0 
            OR CHARINDEX(''' + cast(@searchString as varchar(max)) + ''', [Description]) > 0
            OR CHARINDEX(''' + cast(@searchString as varchar(max)) + ''', [Manufacturer]) > 0))'
    END
END
EXEC (@sql)

再次感谢,丹

于 2012-08-10T15:24:08.357 回答