Как найти строку внутри всей базы данных? - PullRequest
44 голосов
/ 08 декабря 2011

У меня есть одна конкретная строка, такая как, например, «123abcd», но я не знаю ни имени таблицы, ни даже названия столбца внутри таблицы в моей базе данных SQL Server. Я хочу найти его с помощью выбора и показать все столбцы связанной строки, поэтому мне было интересно что-то вроде:

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

По понятным причинам это не работает, но есть простой способ создать оператор выбора, чтобы сделать что-то подобное?

Ответы [ 10 ]

28 голосов
/ 08 декабря 2011

Это будет работать:

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. Если нет совпадений, вы не получите никаких строк назад.

12 голосов
/ 11 сентября 2013

Вот еще пара бесплатных инструментов, которые можно использовать для этого. Оба работают как надстройки SSMS.

ApexSQL Search - 100% бесплатно - поиск и схемы, и данных в таблицах. Имеет несколько полезных опций, таких как отслеживание зависимостей ...

Пакет инструментов SSMS - бесплатно для всех версий, кроме SQL 2012 - не выглядит таким же продвинутым, как предыдущая, но обладает множеством других интересных функций.

4 голосов
/ 07 апреля 2014
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 голосов
/ 08 декабря 2011

Я думаю, у вас есть варианты:

  1. Создание динамического SQL с использованием sys.tables и sys.columns для выполнения поиска ( пример здесь ).

  2. Используйте любую программу, имеющую эту функцию.Примером этого является SQL Workbench (бесплатно).

3 голосов
/ 08 декабря 2011

В oracle вы можете использовать следующую команду sql для генерации необходимых вам команд sql:

select 
     "select * "
     " from "||table_name||
     " where "||column_name||" like '%123abcd%' ;" as sql_command
from user_tab_columns
where data_type='VARCHAR2';
2 голосов
/ 17 июля 2017

Извините за поздний ответ, но я только что задал этот вопрос и в итоге решил его, используя другой подход, который, вероятно, является более общим для всех баз данных.

  1. создать дамп базы данных.
  2. Оттуда вы сможете открыть файл в текстовом редакторе и найти нужную строку.
2 голосов
/ 05 ноября 2015

Common Resource Grep (crgrep) будет искать совпадения строк в таблицах / столбцах по имени или содержимому и поддерживает ряд БД, включая SQLServer, Oracle и другие.Полный подстановочный знак и другие полезные опции.

Это с открытым исходным кодом (я автор).

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

2 голосов
/ 08 декабря 2011

Локатор SQL (бесплатно) отлично работает для меня. Он поставляется с большим количеством опций и довольно прост в использовании.

2 голосов
/ 08 декабря 2011

Я обычно использую information_Schema.columns и information_schema.tables, хотя, как сказал @yuck, sys.tables и sys.columns короче, чтобы набрать.

Затем выполните получившийся sql.

0 голосов
/ 09 августа 2017

Вот простое и удобное решение на основе курсора

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
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...