如何在表格中搜索所有列?

31

如何在SQL Server中搜索表的所有列?


如果只是在查找问题时进行临时搜索,您可以将表转储为 CSV 文件,然后手动搜索。查询语句为:where column1 = 'val' or column2 = 'val' or column 等等。 - carpii
请提供更多信息或您已经尝试过的示例。 - msarchet
你想要搜索的列是什么类型?文本?整数?还是其他类型?即使它们具有不同的类型,你是否也想要搜索所有列? - Mark Byers
有没有更简单的方法? - ahmadali shafiee
Mark Byers:是的,我的表中有nvarchar和int。 - ahmadali shafiee
这是一个一次性或很少使用的查询吗?您可以使用DMV生成SQL来搜索表中的所有字符串列或整个数据库(甚至是连接上的所有数据库)。 - Rob Garrison
6个回答

45
SELECT ...
FROM yourtable
WHERE 'val' IN (field1, field2, field3, field4, ...)

如果你要寻找完全匹配的字段,那么可以直接进行查找。但如果你要寻找子字符串的匹配,则需要采用较为繁琐的方法:

WHERE field1 LIKE '%val%' or field2 LIKE '%val%' etc....

1
有没有更简单的方法? - ahmadali shafiee
13
有时候,你必须得下一些功夫来明确一个复杂的查询,而不是试图寻找捷径。这就是其中之一。 - Marc B
1
如果表中有很多列,那么存储过程可能会出现很多错误。 - ahmadali shafiee
1
如果表中有很多列,那么存储过程可能会出现很多错误。这意味着数据库很混乱吗?对于一个非常大的查询,我会将列标题复制到Excel中批量编辑语法,然后粘贴到记事本中并删除不必要的制表符等,最后再粘贴到SQL查询构建器中。虽然速度快,但并不能解决真正的问题——混乱的数据库。 - Bevan
1
@MarcB 如果我在MYSQL表中有50或60列,那么如何实现高效的搜索呢?我应该如何检查用户输入的关键字是否与任何列值匹配。我已经使用了您提供的第二种方法,但运行时间太长。我应该如何实现更高效的搜索呢?请您帮帮我。 - Pranav MS
2
@MarcB 我的表格中有274列。按照你的逻辑,我甚至不应该查询任何东西,而是应该手动“做这项工作”,在我的130万行数据中手动查找匹配项。 - user3932000

18

你甚至可以这样做。动态创建查询。

CREATE PROC SearchSpecificTable
(
@SearchStr nvarchar(100)
)
AS
BEGIN

    SET NOCOUNT ON;
    
    DECLARE @columnName NVARCHAR(100), @SearchStr2 nvarchar(128)
    DECLARE @tableName NVARCHAR(100) = 'TARGET_TABLE'
    DECLARE @sql NVARCHAR(MAX) = 'SELECT * FROM ' + @tableName +' WHERE '
    SET @SearchStr2 = QUOTENAME('%' + @SearchStr + '%','''')
    
    DECLARE columns CURSOR FOR
    SELECT sys.columns.name FROM sys.tables
    INNER JOIN sys.columns ON sys.columns.object_id = sys.tables.object_id
    WHERE sys.tables.name = @tableName
    
    OPEN columns
        FETCH NEXT FROM columns
        INTO @columnName
        
        WHILE @@FETCH_STATUS = 0
        
        BEGIN
        
            SET @sql = @sql + @columnName + ' LIKE ' + @SearchStr2 + ' OR '
            FETCH NEXT FROM columns
            INTO @columnName    
        
        END
    
    CLOSE columns;    
    DEALLOCATE columns;
    
    SET @sql = LEFT(RTRIM(@sql), LEN(@sql) - 2) -- remove last OR
    
    EXEC(@sql)
END

当然,您可以将 DECLARE @tableName NVARCHAR(100) = 'TARGET_TABLE' 更改为存储过程的参数。

您可以使用以下方式调用它: EXEC SearchSpecificTable @SearchStr = 'needle_to_find';


1
你节省了我的时间,谢谢!这是最好的解决方案。非常感谢。 - Hassan Badawi
一些编辑以使其正常工作。 - Carmageddon

11

我认为这件事没有捷径,你必须指定要搜索的列的列表。如果你发现自己经常需要这样做,那么你可能可以改进数据库设计。

SELECT * 
FROM MyTable 
WHERE Col1 LIKE '%foo%' OR 
      Col2 LIKE '%foo%' OR  
      Col3 LIKE '%foo%' OR 
      Col4 LIKE '%foo%' OR 
      Col5 LIKE '%foo%' OR 
      Col6 LIKE '%foo%'

很好的回答Dylan,如果我们去掉%符号,它将精确搜索'foo'位。 - Bevan

9

我不能为此负责,但我发现这样做非常有效。您可以将其他数据类型添加到 WHERE 子句中以包含其他类型,如果需要限制搜索,则还可以添加 JOIN 中的模式名称(如下所述)。

DECLARE @SQL VARCHAR(MAX) 
DECLARE @SearchString VARCHAR(100) 
SET @SQL='' 

-- ------------------------------------------ 
-- Enter the string to be searched for here : 
SET @SearchString='' 
-- ------------------------------------------ 

SELECT   @SQL = @SQL + 'SELECT CONVERT(VARCHAR(MAX),COUNT(*)) + '' matches in column ''+'''
     + C.name + '''+'' on table '' + ''' + SC.name + '.' + T.name + 
     ''' [Matches for '''+@SearchString+''':] FROM ' + 
     QUOTENAME(SC.name) + '.' + QUOTENAME(T.name) + ' WHERE ' + QUOTENAME(C.name) + 
     ' LIKE ''%' + @SearchString + 
     '%'' HAVING COUNT(*)>0 UNION ALL ' +CHAR(13) + CHAR(10) 

FROM     sys.columns C 
JOIN     sys.tables T ON C.object_id=T.object_id 
JOIN     sys.schemas SC ON SC.schema_id=T.schema_id -- AND SC.name = ''
JOIN     sys.types ST ON C.user_type_id=ST.user_type_id 
JOIN     sys.types SYST ON ST.system_type_id=SYST.user_type_id
    AND ST.system_type_id=SYST.system_type_id 

WHERE    SYST.name IN ('varchar','nvarchar','text','ntext','char','nchar') 

ORDER BY T.name, C.name 

-- Strip off the last UNION ALL 

IF LEN(@SQL)>12 
  SELECT @SQL=LEFT(@SQL,LEN(@SQL)- 12) 

EXEC(@SQL) 
--PRINT @SQL

Reference: https://www.sqlmatters.com/Articles/Searching%20all%20columns%20in%20all%20tables%20in%20a%20database.aspx


4

我之前在一个项目中就做过这件事。在SQL中搜索所有列的最佳方法是在表格中创建一个新列,并将每列的文本/数据粘贴到其中,如下所示:

表格:
|---------------------------------------------------|
| column1 | column2 | search_column |
|---------------------------------------------------|
| fooxxxxx | barxxxx | fooxxxxx barxxxx |
----------------------------------------------------|

SELECT search_column FROM table1 LIKE %关键词%

这样做可以快速实现目标,而且不需要编写大量的SQL代码。这种查询方式也更快速。唯一的缺点是当更新和创建表格时,必须重新构造search_column。


这是一个非常简单的解决方案,这让我更加喜欢它。为了解决你的缺点,你可以使用带有列的物化视图。你还需要使用WHERE LIKE '关键词%'或LIKE '%关键词'或LIKE '%关键词%'来概括查询。 - BBQ Singular

3
读完Jose Hernandez Naranjo的答案后,我找到了一种快速的方法,使用子查询。这样做的好处是我们不必在数据库中添加额外的列。
假设我们有一个名为person的表,其中包含PersonID、Firstname、Name、Cellphone、Email和Place等列,这些列都需要进行搜索,并且应该输出包括地点的全名。那么代码应该如下所示:
SELECT Firstname, Name, Place 
FROM person NATURAL JOIN 
  (SELECT PersonID, CONCAT(Firstname, ' ', Name, ' ', Cellphone, ' ',
   Email, ' ', Place) search_string FROM person) as all_in_one
WHERE search_string LIKE '%Hans%' AND search_string LIKE '%Muster%'

如果您正在使用来自另一种语言(如PHP)的SQL,您可以使用循环添加WHERE后面的部分。以下是一个来自PHP的示例:

$q = $_GET['q'];
$words = explode(" ", $q);
foreach($words as $word){
  if(is_null($search_query)){
     $search_query = "search_string LIKE '%$word%'";
  }else{
     $search_query .= " AND search_string LIKE '%$word%'";
  }     
}

(注意:此示例未对GET变量进行任何检查,可能会被用于SQL注入攻击。)

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接