2012-08-09 60 views
0

我可以在WHERE子句中放置WHILE循環嗎?我有一個存儲過程,我試圖把文本搜索功能。我有這樣的一個完全匹配的工作:SQL WHILE WHERE子句中的循環

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 

現在我想用@searchString變量就像我上面使用@exactString。有沒有辦法在我的循環內做到這一點,或者是否有一些我錯過的其他技術可以在這裏工作?

感謝您的幫助, 丹

+3

沒有任何理由,爲什麼你不使用[全文搜索(http://msdn.microsoft.com /en-us/library/ms142571.aspx)? – swasheck 2012-08-09 20:20:43

+0

[搜索SQL Server索引中的詞]可能的重複(http://stackoverflow.com/questions/156954/search-for-words-in-sql-server-index) – Tony 2012-08-09 20:32:19

+0

@swasheck - 我第一次碰到在研究這篇文章中的全文搜索時表示「假設你在SQL 2008上」,這是我們沒有的(2005),所以我認爲這對我不起作用。 – 2012-08-10 12:12:53

回答

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 
+0

這完全做了「任何」搜索的伎倆。我已經有了一個CLR_charlist_split函數(來自http://www.sommarskog.se/arrays-in-sql-2005.html),我用它來分割表,但是用join和LIKE來做並沒有發生我。謝謝! – 2012-08-10 17:41:43

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) 

感謝, 丹

+0

你願意分享一些關於這個查詢速度的信息(和邁克爾給你的)嗎?我很想知道您搜索的記錄數量以及返回結果的時間。我並不蔑視這個問題,我只是很想知道。 – Tony 2012-08-12 21:10:58