以任何顺序跨多个列进行SQL搜索

时间:2014-11-06 23:39:04

标签: sql-server

我的用户正在尝试通过提供如下所示的简单文本字符串来查找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','000012312','121-0000121515' UNION
SELECT 'SM01','000000152','121-0000155' UNION
SELECT 'TH01','000123151','TMB-0000000025'

SELECT * FROM @table

一个额外的皱纹,用户无需输入000000152,他们可以输入152,它应该会找到相同的结果。

我可以使用patindex,但它要求用户按特定顺序输入搜索字词,或者让我有一个指数级较大的字符串进行比较,因为我尝试将它们置于所有可能的安排中。

在SQL中执行此操作的最佳方法是什么?或者,这是否超出SQL的能力?该表很可能有超过10,000条记录(有些情况甚至超过100,000条记录),因此查询必须高效。

2 个答案:

答案 0 :(得分:1)

同意@MitchWheat(照例)。此数据库不是为这样的查询而设计的,也不是任何类型的基本查询"救命。最好的方法是构建一个出现在数据库任何列中的字符串列表,映射回源列和行,并在该查找表中搜索字符串。这几乎是Lucene和任何其他全文搜索库将为您做的事情。 SQL有一个本地实现,但如果专业人士说与第三方实现一起使用,我说它值得一看。

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