【问题标题】:How to find a string inside a entire database?如何在整个数据库中查找字符串?
【发布时间】:2012-01-16 04:23:39
【问题描述】:

我有一个特定的字符串,例如“123abcd”,但我不知道表的名称,甚至不知道我的 SQL Server 数据库中表中列的名称。我想通过选择找到它并显示相关字符串的所有列,所以我想知道类似:

select * from Database.dbo.* where * like  '%123abcd%'

由于显而易见的原因它不起作用,但是有一种简单的方法可以创建一个 select 语句来执行类似的操作?

【问题讨论】:

  • 你为什么不问问系统开发人员或DBA在哪里可以找到它?正是这样的事情让开发人员和 DBA 产生了分歧;)
  • 数据库有多大?性能是个问题吗?
  • 3GB数据库,性能没问题。
  • 您将不得不编写一些非常糟糕的动态 SQL 并查询系统目录(sys.schemassys.tablessys.columns)来做到这一点。
  • 这个功能在 phpmyadmin 和 MySQL 中可用!啊痛苦..

标签: sql database sql-server-2008 select


【解决方案1】:

这将起作用:

DECLARE @MyValue NVarChar(4000) = 'something';

SELECT S.name SchemaName, T.name TableName
INTO #T
FROM sys.schemas S INNER JOIN
     sys.tables T ON S.schema_id = T.schema_id;

WHILE (EXISTS (SELECT * FROM #T)) BEGIN
  DECLARE @SQL NVarChar(4000) = 'SELECT * FROM $$TableName WHERE (0 = 1) ';
  DECLARE @TableName NVarChar(1000) = (
    SELECT TOP 1 SchemaName + '.' + TableName FROM #T
  );
  SELECT @SQL = REPLACE(@SQL, '$$TableName', @TableName);

  DECLARE @Cols NVarChar(4000) = '';

  SELECT
    @Cols = COALESCE(@Cols + 'OR CONVERT(NVarChar(4000), ', '') + C.name + ') = CONVERT(NVarChar(4000), ''$$MyValue'') '
  FROM sys.columns C
  WHERE C.object_id = OBJECT_ID(@TableName);

  SELECT @Cols = REPLACE(@Cols, '$$MyValue', @MyValue);
  SELECT @SQL = @SQL + @Cols;

  EXECUTE(@SQL);

  DELETE FROM #T
  WHERE SchemaName + '.' + TableName = @TableName;
END;

DROP TABLE #T;

不过,有几点需要注意。首先,这是非常缓慢且未经优化的。所有值都被转换为nvarchar,以便可以毫无错误地比较它们。您可能会遇到诸如 datetime 之类的值未按预期转换的问题,因此在它们应该匹配时未匹配(假阴性)。

WHERE (0 = 1) 可以使构建OR 子句更容易。如果没有匹配项,您将不会返回任何行。

【讨论】:

    【解决方案2】:

    这里有更多免费工具可用于此目的。两者都作为 SSMS 插件工作。

    ApexSQL Search - 100% 免费 - 搜索表中的模式和数据。有几个更有用的选项,例如依赖跟踪……

    SSMS Tools pack - 除 SQL 2012 之外的所有版本都免费 - 看起来不像以前的版本那么先进,但还有许多其他很酷的功能。

    【讨论】:

    • 可以确认,ApexSQL 救了我,它是最新的,连接最新的 SQL Server 和 Visual Studio。
    • ApexSQL 从 SMSS 2012 开始,所以对于 2008 R2,我不得不使用 SMSS Tools Pack,但这对我有用。
    • 如果你喜欢/需要一个命令行工具,我在这里写了一个开源工具:github.com/nzbart/sqlgrep
    【解决方案3】:

    我认为你必须选择:

    1. 使用sys.tablessys.columns 构建动态SQL 以执行搜索(example here)。

    2. 使用任何具有此功能的程序。 SQL Workbench(免费)就是一个例子。

    【讨论】:

      【解决方案4】:
      create procedure usp_find_string(@string as varchar(1000))
      as
      begin
      declare @mincounter as int
      declare @maxcounter as int
      declare @stmtquery as varchar(1000)
      set @stmtquery=''
      create table #tmp(tablename varchar(128),columnname varchar(128),rowid int identity)
      create table #tablelist(tablename varchar(128),columnname varchar(128))
      declare @tmp table(name varchar(128))
      declare @tablename as varchar(128)
      declare @columnname as varchar(128)
      
      insert into #tmp(tablename,columnname)
      select a.name,b.name as columnname from sysobjects a
      inner join syscolumns b on a.name=object_name(b.id)
      where a.type='u'
      and b.xtype in(select xtype from systypes
          where name='text' or name='ntext' or name='varchar' or name='nvarchar' or name='char' or name='nchar')
      order by a.name
      
      select @maxcounter=max(rowid),@mincounter=min(rowid) from #tmp 
      while(@mincounter <= @maxcounter )
      begin
       select @tablename=tablename, @columnname=columnname from #tmp where rowid=@mincounter
       set @stmtquery ='select top 1  ' + '[' +@columnname+']' + ' from ' + '['+@tablename+']' + ' where ' + '['+@columnname+']' + ' like ' + '''%' + @string + '%'''
       insert into @tmp(name) exec(@stmtquery)
       if @@rowcount >0
       insert into #tablelist values(@tablename,@columnname)
       set @mincounter=@mincounter +1
      end
      select * from #tablelist
      end
      

      【讨论】:

        【解决方案5】:

        在oracle中你可以使用下面的sql命令来生成你需要的sql命令:

        select 
             "select * "
             " from "||table_name||
             " where "||column_name||" like '%123abcd%' ;" as sql_command
        from user_tab_columns
        where data_type='VARCHAR2';
        

        【讨论】:

          【解决方案6】:

          Common Resource Grep (crgrep) 将按名称或内容在表/列中搜索字符串匹配项,并支持许多 DB,包括 SQLServer、Oracle 等。完整的通配符和其他有用的选项。

          它是开源的(我是作者)。

          http://sourceforge.net/projects/crgrep/

          【讨论】:

            【解决方案7】:

            我通常使用information_Schema.columnsinformation_schema.tables,尽管就像@yuck 所说,sys.tablessys.columns 打字更短。

            在一个循环中,连接这些

            @sql = @sql + 'select' + column_name + 
            ' from ' + table_name + 
            ' where ' + column_name ' like ''%''+value+''%' UNION
            

            然后执行生成的sql。

            【讨论】:

            • 我相信 INFORMATION_SCHEMA 的东西已被弃用。尽管它们确实提供了一些 sys DMV 没有提供的值。其中之一是表中列的序号位置。为此,我不得不依赖旧的观点。
            【解决方案8】:

            这是一个简单方便的基于光标的解决方案

            DECLARE
            @search_string  VARCHAR(100),
            @table_name     SYSNAME,
            @table_id       INT,
            @column_name    SYSNAME,
            @sql_string     VARCHAR(2000)
            
            SET @search_string = 'StringtoSearch'
            
            DECLARE tables_cur CURSOR FOR SELECT name, object_id FROM sys.objects WHERE  type = 'U'
            
            OPEN tables_cur
            
            FETCH NEXT FROM tables_cur INTO @table_name, @table_id
            
            WHILE (@@FETCH_STATUS = 0)
            BEGIN
                DECLARE columns_cur CURSOR FOR SELECT name FROM sys.columns WHERE object_id = @table_id 
                    AND system_type_id IN (167, 175, 231, 239)
            
                OPEN columns_cur
            
                FETCH NEXT FROM columns_cur INTO @column_name
                    WHILE (@@FETCH_STATUS = 0)
                    BEGIN
                        SET @sql_string = 'IF EXISTS (SELECT * FROM ' + @table_name + ' WHERE [' + @column_name + '] 
                        LIKE ''%' + @search_string + '%'') PRINT ''' + @table_name + ', ' + @column_name + ''''
            
                        EXECUTE(@sql_string)
            
                    FETCH NEXT FROM columns_cur INTO @column_name
                    END
            
                CLOSE columns_cur
            
            DEALLOCATE columns_cur
            
            FETCH NEXT FROM tables_cur INTO @table_name, @table_id
            END
            
            CLOSE tables_cur
            DEALLOCATE tables_cur
            

            【讨论】:

              猜你喜欢
              • 1970-01-01
              • 1970-01-01
              • 2019-10-28
              • 1970-01-01
              • 1970-01-01
              • 1970-01-01
              • 1970-01-01
              • 2015-01-29
              • 2012-12-15
              相关资源
              最近更新 更多