Как найти строку внутри всей базы данных?
У меня есть одна конкретная строка, например, "123abcd", но я не знаю имя таблицы или даже имя столбца внутри таблицы в моей базе данных SQL Server. Я хочу найти его с помощью select и показать все столбцы связанной строки, поэтому мне было интересно что-то вроде:
select * from Database.dbo.* where * like '%123abcd%'
По понятным причинам он не работает, но есть простой способ создать оператор 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 - бесплатный для всех версий, кроме SQL 2012 - не выглядит таким передовым, как предыдущий, но имеет много других интересных функций.
Ответ 3
Думаю, у вас есть варианты:
-
Создайте динамический SQL с помощью sys.tables
и sys.columns
для выполнения поиска (пример здесь).
-
Используйте любую программу, которая имеет эту функцию. Примером этого является 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 [email protected]
set @stmtquery ='select top 1 ' + '[' [email protected]+']' + ' from ' + '['[email protected]+']' + ' where ' + '['[email protected]+']' + ' like ' + '''%' + @string + '%'''
insert into @tmp(name) exec(@stmtquery)
if @@rowcount >0
insert into #tablelist values(@tablename,@columnname)
set @[email protected] +1
end
select * from #tablelist
end
Ответ 5
В оракуле вы можете использовать следующую команду sql для генерации необходимых вам команд sql:
select
"select * "
" from "||table_name||
" where "||column_name||" like '%123abcd%' ;" as sql_command
from user_tab_columns
where data_type='VARCHAR2';
Ответ 6
Я обычно использую 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.
Ответ 7
SQL Locator (бесплатно) отлично поработал у меня. Он поставляется с множеством опций и довольно прост в использовании.
Ответ 8
Common Resource Grep (crgrep) будет искать соответствия строк в таблицах/столбцах по имени или контенту и поддерживает несколько БД, включая SQLServer, Oracle и другие. Полный дикий кардинг и другие полезные опции.
Это openource (я автор).
http://sourceforge.net/projects/crgrep/
Ответ 9
Извините за поздний ответ, но у меня тоже был этот вопрос, и я решил его решить, используя другой подход, который, вероятно, более общий для всех баз данных.
- создать дамп базы данных.
- Оттуда вы сможете открыть файл в текстовом редакторе и найти нужную строку.
Ответ 10
Вот решение на основе курсора
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