WHERE子句中的SQL WHILE循环

时间:2012-08-09 20:16:47

标签: sql-server

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

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

接下来我试着做一个"任何一个词"匹配和#34;所有单词"比赛。我可以通过以下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

现在我想使用@searchString变量,就像我上面使用@exactString一样。有没有办法在我的循环中执行此操作,或者是否有其他一些我不会在这里工作的技术?

感谢您的帮助, 丹

2 个答案:

答案 0 :(得分: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

答案 1 :(得分:0)

我得到了迈克尔埃里克森的一个很好的答案,完全适用于“任何”搜索。对于“全部”搜索。我用整个查询构建了一个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)

再次感谢, 丹