web-dev-qa-db-ja.com

データベース全体で文字列を見つける方法は?

たとえば、「123abcd」などの特定の文字列が1つありますが、SQL Serverデータベースのテーブルの名前やテーブル内の列の名前さえわかりません。私は選択でそれを見つけて、関連する文字列のすべての列を表示したいので、次のようなものを考えていました:

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

明らかな理由で機能しませんが、selectステートメントを作成してこのようなことをする簡単な方法はありますか?

44
Diogo

これは動作します:

_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句の構築を容易にするためにあります。一致するものがない場合、行は戻されません。

28
Yuck

これに使用できる無料のツールがいくつかあります。両方ともSSMSアドインとして機能します。

ApexSQL Search – 100%free-スキーマとテーブル内のデータの両方を検索します。依存関係の追跡など、さらに便利なオプションがいくつかあります…

SSMSツールパック – SQL 2012を除くすべてのバージョンで無料–以前のバージョンほど高度ではありませんが、他の多くのクールな機能があります。

13
John Moore
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
4

あなたにはオプションが必要だと思います:

  1. sys.tablesおよびsys.columnsを使用して動的SQLを作成し、検索を実行します( example here )。

  2. この機能を持つプログラムを使用します。この例は SQL Workbench (無料)です。

4
DavidEG

Oracleでは、次のsqlコマンドを使用して、必要なsqlコマンドを生成できます。

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

SQL Locator (無料)は、私にとって非常にうまく機能しました。それは多くのオプションが付属しており、それはかなり使いやすいです。

2
Gabe

共通リソースGrep(crgrep)は、名前または内容によってテーブル/列の文字列一致を検索し、SQLServer、Oracleなどを含む多数のDBをサポートします。完全なワイルドカードとその他の便利なオプション。

それはオープンソースです(私は著者です)。

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

2
Craig

私は通常information_Schema.columnsおよびinformation_schema.tables、@ yuckが言ったように、sys.tablesおよびsys.columnsは入力が短くなります。

ループで、これらを連結します

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

次に、結果のSQLを実行します。

2
MatthewMartin

回答が遅れてすみませんが、この質問もありましたが、すべてのデータベースに対してより一般的な別のアプローチを使用して解決しました。

  1. データベースダンプを作成します。
  2. そこからテキストエディターでファイルを開き、必要な文字列を検索できるはずです。
2
meowcat

これは簡単で便利なカーソルベースのソリューションです

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
0
Noor A Shuvo