2014-11-06 54 views
0

我的用戶試圖通過提供簡單的文本字符串這樣找到我的SQL數據庫記錄:SQL搜索以任意順序

SCRAP 000000152 TMB-0000000025

這些值可以是任何順序和任何可能排除。例如,他們可能會進入:

SCRAP TMB-0000000025 SCRAP 000000152 SCRAP SCRAP 000000152 TMB-0000000025 000000152

所有應該工作,包括相同的記錄作爲原本的搜索,但他們可能還包含其他記錄,因爲更少的列中使用比賽。

下面是使用結果的示例表:

DECLARE @search1 varchar(50) = 'SCRAP 000000152 TMB-0000000025' 
DECLARE @search2 varchar(50) = 'SCRAP' 
DECLARE @search3 varchar(50) = 'TMB-0000000025 SCRAP' 
DECLARE @search4 varchar(50) = '000000152 SCRAP' 
DECLARE @search5 varchar(50) = 'SCRAP 000000152' 
DECLARE @search6 varchar(50) = 'TMB-0000000025 000000152' 

DECLARE @table TABLE (WC varchar(20),WO varchar(20),PN varchar(20)) 
INSERT INTO @table 
SELECT 'SCRAP','000000152','TMB-0000000025' UNION 
SELECT 'SCRAP','000','121-0000121515' UNION 
SELECT 'SM01','000000152','121-0000155' UNION 
SELECT 'TH01','00','TMB-0000000025' 

SELECT * FROM @table 

一個額外的皺紋,用戶不必進入000000152,他們可以進入152,它應該發現相同的結果。

我可以使用patindex,但它需要用戶按照特定的順序輸入搜索詞,或者對於我來說,有一個指數級更大的字符串來比較,因爲我嘗試將它們放入所有可能的排列中。

在SQL中執行此操作的最佳方法是什麼?或者,這是否超出了SQL的功能?該表很可能擁有超過10,000條記錄(對於某些情況甚至超過100,000條記錄),因此查詢必須高效。

+0

使用lucene ..... – 2014-11-06 23:54:31

+0

@MitchWheat,你是說在SQL中沒有好的方法嗎? – davids 2014-11-06 23:56:14

+2

我在說,解決你的問題的最好方法是使用Lucene。你的問題指出:「做這件事的最好方法是什麼?」 – 2014-11-06 23:56:43

回答

1

同意@MitchWheat(照常)。這個數據庫不是爲這樣的查詢而設計的,任何種類的「基本查詢」都不會有幫助。最好的方法是創建出現在數據庫的任何列中的字符串列表,映射回源列和行,然後在查找表中搜索字符串。這幾乎是Lucene和任何其他全文搜索庫會爲你做的。 SQL有一個本地實現,但如果專業人士說與第三方實現,我會說這是值得一看。

0

你可以試試這個SP:

USE master 
GO 

CREATE PROCEDURE sp_FindStringInTable @stringToFind VARCHAR(100), @schema sysname, @table sysname 
AS 

DECLARE @sqlCommand VARCHAR(8000) 
DECLARE @where VARCHAR(8000) 
DECLARE @columnName sysname 
DECLARE @cursor VARCHAR(8000) 

BEGIN TRY 
    SET @sqlCommand = 'SELECT * FROM [' + @schema + '].[' + @table + '] WHERE' 
    SET @where = '' 

    SET @cursor = 'DECLARE col_cursor CURSOR FOR SELECT COLUMN_NAME 
    FROM ' + DB_NAME() + '.INFORMATION_SCHEMA.COLUMNS 
    WHERE TABLE_SCHEMA = ''' + @schema + ''' 
    AND TABLE_NAME = ''' + @table + ''' 
    AND DATA_TYPE IN (''char'',''nchar'',''ntext'',''nvarchar'',''text'',''varchar'')' 

    EXEC (@cursor) 

    OPEN col_cursor  
    FETCH NEXT FROM col_cursor INTO @columnName  

    WHILE @@FETCH_STATUS = 0  
    BEGIN  
     IF @where <> '' 
      SET @where = @where + ' OR' 

     SET @where = @where + ' [' + @columnName + '] LIKE ''' + @stringToFind + '''' 
     FETCH NEXT FROM col_cursor INTO @columnName  
    END  

    CLOSE col_cursor  
    DEALLOCATE col_cursor 

    SET @sqlCommand = @sqlCommand + @where 
    --PRINT @sqlCommand 
    EXEC (@sqlCommand) 
END TRY 
BEGIN CATCH 
    PRINT 'There was an error. Check to make sure object exists.' 
    IF CURSOR_STATUS('variable', 'col_cursor') <> -3 
    BEGIN 
     CLOSE col_cursor  
     DEALLOCATE col_cursor 
    END 
END CATCH 

這將有結果如下:

USE AdventureWorks 
GO 
EXEC sp_FindStringInTable 'Irv%', 'Person', 'Address' 

enter image description here

USE AdventureWorks 
GO 
EXEC sp_FindStringInTable '%land%', 'Person', 'Address' 

enter image description here 這一切就是這麼簡單。一旦創建完成,你可以在服務器上的任何表和任何數據庫上使用它。(Read More

+0

這是一種在任何字段中查找單個字符串(或部分字符串)的方法,但我需要找到一個記錄,該記錄在幾個字段中具有幾個分支的匹配項。它可能適合我的需要,但我懷疑它將遠沒有效率。 – davids 2014-11-07 15:02:57