Как искать в базе данных sql server строку? - PullRequest
98 голосов
/ 08 февраля 2012

Я знаю, что это возможно, но не знаю как.

Мне нужно найти в базе данных Microsoft SQL все упоминания о конкретной строке.Например: я хотел бы найти во всех таблицах, представлениях, функциях, хранимых процедурах ... строку "tblEmployes".(Не данные в таблицах)

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

Любая помощь приветствуется.

Ответы [ 15 ]

129 голосов
/ 08 февраля 2012

это будет искать каждый столбец каждой таблицы в конкретной базе данных. создайте сохраненный процесс в базе данных, в которой вы хотите искать.

http://blogs.lessthandot.com/index.php/DataMgmt/DataDesign/the-ten-most-asked-sql-server-questions--1#2:

CREATE PROCEDURE FindMyData_String
    @DataToFind NVARCHAR(4000),
    @ExactMatch BIT = 0
AS
SET NOCOUNT ON

DECLARE @Temp TABLE(RowId INT IDENTITY(1,1), SchemaName sysname, TableName sysname, ColumnName SysName, DataType VARCHAR(100), DataFound BIT)

    INSERT  INTO @Temp(TableName,SchemaName, ColumnName, DataType)
    SELECT  C.Table_Name,C.TABLE_SCHEMA, C.Column_Name, C.Data_Type
    FROM    Information_Schema.Columns AS C
            INNER Join Information_Schema.Tables AS T
                ON C.Table_Name = T.Table_Name
        AND C.TABLE_SCHEMA = T.TABLE_SCHEMA
    WHERE   Table_Type = 'Base Table'
            And Data_Type In ('ntext','text','nvarchar','nchar','varchar','char')


DECLARE @i INT
DECLARE @MAX INT
DECLARE @TableName sysname
DECLARE @ColumnName sysname
DECLARE @SchemaName sysname
DECLARE @SQL NVARCHAR(4000)
DECLARE @PARAMETERS NVARCHAR(4000)
DECLARE @DataExists BIT
DECLARE @SQLTemplate NVARCHAR(4000)

SELECT  @SQLTemplate = CASE WHEN @ExactMatch = 1
                            THEN 'If Exists(Select *
                                          From   ReplaceTableName
                                          Where  Convert(nVarChar(4000), [ReplaceColumnName])
                                                       = ''' + @DataToFind + '''
                                          )
                                     Set @DataExists = 1
                                 Else
                                     Set @DataExists = 0'
                            ELSE 'If Exists(Select *
                                          From   ReplaceTableName
                                          Where  Convert(nVarChar(4000), [ReplaceColumnName])
                                                       Like ''%' + @DataToFind + '%''
                                          )
                                     Set @DataExists = 1
                                 Else
                                     Set @DataExists = 0'
                            END,
        @PARAMETERS = '@DataExists Bit OUTPUT',
        @i = 1

SELECT @i = 1, @MAX = MAX(RowId)
FROM   @Temp

WHILE @i <= @MAX
    BEGIN
        SELECT  @SQL = REPLACE(REPLACE(@SQLTemplate, 'ReplaceTableName', QUOTENAME(SchemaName) + '.' + QUOTENAME(TableName)), 'ReplaceColumnName', ColumnName)
        FROM    @Temp
        WHERE   RowId = @i


        PRINT @SQL
        EXEC SP_EXECUTESQL @SQL, @PARAMETERS, @DataExists = @DataExists OUTPUT

        IF @DataExists =1
            UPDATE @Temp SET DataFound = 1 WHERE RowId = @i

        SET @i = @i + 1
    END

SELECT  SchemaName,TableName, ColumnName
FROM    @Temp
WHERE   DataFound = 1
GO

чтобы запустить его, просто сделайте это:

exec FindMyData_string 'google', 0

работает на удивление хорошо !!!

58 голосов
/ 08 февраля 2012

Если вам нужно найти объекты базы данных (например, таблицы, столбцы, триггеры) по имени - взгляните на FREE Red-Gate инструмент под названием SQL Search , который делает это - он ищет во всей вашей базе данных любые типы строк.

enter image description here

enter image description here

Это отличный обязательный инструмент для любого администратора БД или разработчика базы данных - я уже упоминал, что это абсолютно БЕСПЛАТНО для использования в любых целях ??

45 голосов
/ 13 марта 2013

Вы также можете попробовать ApexSQL Search - это бесплатное дополнение SSMS, похожее на SQL Search.

Если вы действительно хотите использовать только sql, вы можете попробовать этот скрипт

select 
S.name as [Schema], 
o.name as [Object], 
o.type_desc as [Object_Type], 
C.text as [Object_Definition]
from sys.all_objects O inner join sys.schemas S on O.schema_id = S.schema_id
inner join sys.syscomments C on O.object_id = C.id
where S.schema_id not in (3,4) -- avoid searching in sys and INFORMATION_SCHEMA schemas
and C.text like '%ICE_%'
order by [Schema]
17 голосов
/ 08 февраля 2012

Для получения таблицы по имени на сервере sql:

SELECT *
FROM sys.Tables
WHERE name LIKE '%Employees%'

для поиска хранимой процедуры по имени:

SELECT name
FROM sys.objects
WHERE name = 'spName'

для получения всех хранимых процедур, связанных с таблицей:

----Option 1
SELECT DISTINCT so.name
FROM syscomments sc
INNER JOIN sysobjects so ON sc.id=so.id
WHERE sc.TEXT LIKE '%tablename%'
----Option 2
SELECT DISTINCT o.name, o.xtype
FROM syscomments c
INNER JOIN sysobjects o ON c.id=o.id
WHERE c.TEXT LIKE '%tablename%'
15 голосов
/ 17 декабря 2012

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

5 голосов
/ 21 апреля 2016

Эта процедура поиска кода и функция, но не поиск в таблице:)

SELECT name FROM   sys.all_objects WHERE  Object_definition(object_id) LIKE '%text%' ORDER BY name
3 голосов
/ 08 февраля 2012

вы могли бы;

  1. Сценарий базы данных в один файл и поиск файла для tblEmployees, используя текст редактор. В средствах управления SQL Server (SSMS) щелкните правой кнопкой мыши базу данных и выберите «Создать сценарии».
  2. Используйте SSMS «Просмотр зависимостей», щелкнув правой кнопкой мыши tblEmployees, чтобы увидеть, какие другие объекты зависят от него
  3. Используйте бесплатный сторонний инструмент, такой как RedGate SQLSearch, для поиска всех объектов базы данных по имени и содержимому по ключевому слову.
2 голосов
/ 25 октября 2017

Был предоставлен доступ к базе данных, но не к таблице, в которой хранился мой запрос.

Вдохновленный ответом @marc_s, я посмотрел на HeidiSQL , программу для Windows, которая может работать с MySQL, MSSQL и PostgreSQL.

Обнаружено, что он также может искать в базе данных строку.

Click Search, then Find text on Server

Search tool open. Make sure the DB is selected

Он будет искать в каждой таблице и подсчитывать, сколько раз найдена строка в таблице!

2 голосов
/ 11 января 2017

Старый вопрос, я знаю, но здесь идет моя версия ... Я назвал ее "Игла в стоге сена" по понятным причинам.

Он ищет конкретное значение в каждой строке и каждом столбце, а не дляимена столбцов и т. д.

Выполните поиск (конечно же, замените значения для первых двух переменных):

DECLARE @SEARCH_DB VARCHAR(100)='REPLACE_WITH_YOUR_DB_NAME'
DECLARE @SEARCH_VALUE_LIKE NVARCHAR(100)=N'%REPLACE_WITH_SEARCH_STRING%'

SET NOCOUNT ON;  
DECLARE col_cur CURSOR FOR
SELECT TABLE_CATALOG, TABLE_SCHEMA, TABLE_NAME, COLUMN_NAME, DATA_TYPE
FROM information_schema.columns WHERE TABLE_CATALOG=@SEARCH_DB AND DATA_TYPE NOT IN ('timestamp', 'datetime');

DECLARE @TOTAL int = (SELECT COUNT(*)
FROM information_schema.columns WHERE TABLE_CATALOG=@SEARCH_DB AND DATA_TYPE NOT IN ('timestamp', 'datetime'));


DECLARE @TABLE_CATALOG nvarchar(500), @TABLE_SCHEMA nvarchar(500), @TABLE_NAME nvarchar(500), @COLUMN_NAME nvarchar(500), @DATA_TYPE nvarchar(500);
DECLARE @SQL nvarchar(4000)='';

PRINT '-------- BEGIN SEARCH --------';  
OPEN col_cur;

FETCH NEXT FROM col_cur INTO @TABLE_CATALOG, @TABLE_SCHEMA, @TABLE_NAME, @COLUMN_NAME, @DATA_TYPE;

BEGIN TRY DROP TABLE ##RESULTS; END TRY BEGIN CATCH END CATCH
CREATE TABLE ##RESULTS( TABLE_CATALOG nvarchar(500), TABLE_SCHEMA nvarchar(500), TABLE_NAME nvarchar(500), COLUMN_NAME nvarchar(500), DATA_TYPE nvarchar(500), RECORDS int)  
DECLARE @SHOULD_CAST bit=0
DECLARE @i int =0
DECLARE @progress_sum bigint=0

WHILE @@FETCH_STATUS = 0  
BEGIN
    -- PRINT '' + CAST(@i as varchar(100)) +' of ' + CAST(@TOTAL as varchar(100)) + '  ' + @TABLE_CATALOG+'.'+@TABLE_SCHEMA+'.'+@TABLE_NAME+': '+@COLUMN_NAME+' ('+@DATA_TYPE+')';

    SET @SHOULD_CAST = (SELECT CASE @DATA_TYPE 
                                WHEN 'varchar' THEN 0
                                WHEN 'nvarchar' THEN 0
                                WHEN 'char' THEN 0
                                ELSE 1 END)

    SET @SQL='SELECT '''+@TABLE_CATALOG+''' catalog_name, '''+@TABLE_SCHEMA+''' schema_name, '''+@TABLE_NAME+''' table_name, '''+@COLUMN_NAME+''' column_name, '''+@DATA_TYPE+''' data_type, ' + 
            +' COUNT(['+@COLUMN_NAME+']) records '+
            +' FROM '+@TABLE_CATALOG+'.'+@TABLE_SCHEMA+'.'+@TABLE_NAME +
            +' WHERE ' + CASE WHEN @SHOULD_CAST=1 THEN 'CAST(['+@COLUMN_NAME + '] as NVARCHAR(max)) ' ELSE ' ['+@COLUMN_NAME + '] ' END 
            +' LIKE '''+ @SEARCH_VALUE_LIKE + ''' '

    -- PRINT @SQL;

    IF @i % 100 = 0
        BEGIN
            SET @progress_sum = (SELECT SUM(RECORDS) FROM ##RESULTS)
            PRINT CAST (@i as varchar(100)) +' of ' + CAST(@TOTAL as varchar(100)) +': '+ CAST (@progress_sum as varchar(100))
        END

    INSERT INTO ##RESULTS (TABLE_CATALOG, TABLE_SCHEMA, TABLE_NAME, COLUMN_NAME, DATA_TYPE, RECORDS)
    EXEC(@SQL)

    FETCH NEXT FROM col_cur INTO @TABLE_CATALOG, @TABLE_SCHEMA, @TABLE_NAME, @COLUMN_NAME, @DATA_TYPE;
    SET @i=@i+1
    -- IF @i > 1000
    --  BREAK
END   
CLOSE col_cur;  
DEALLOCATE col_cur;

SELECT * FROM ##RESULTS WHERE RECORDS>0;

Затем, чтобы просмотреть результаты, даже при выполнении, из другого окна, выполните:

DECLARE @SEARCH_VALUE_LIKE NVARCHAR(100)=N'%@FLEX@%'
SELECT * FROM ##RESULTS WHERE RECORDS>0;

SET NOCOUNT ON;  
DECLARE col_cur CURSOR FOR
SELECT TABLE_CATALOG, TABLE_SCHEMA, TABLE_NAME, COLUMN_NAME, DATA_TYPE
FROM ##RESULTS WHERE RECORDS>0;

DECLARE @TABLE_CATALOG nvarchar(500), @TABLE_SCHEMA nvarchar(500), @TABLE_NAME nvarchar(500), @COLUMN_NAME nvarchar(500), @DATA_TYPE nvarchar(500);
DECLARE @SQL nvarchar(4000)='';

OPEN col_cur;

FETCH NEXT FROM col_cur INTO @TABLE_CATALOG, @TABLE_SCHEMA, @TABLE_NAME, @COLUMN_NAME, @DATA_TYPE;
DECLARE @i int =0
DECLARE @SHOULD_CAST bit=0

WHILE @@FETCH_STATUS = 0  
BEGIN
    SET @SHOULD_CAST = (SELECT CASE @DATA_TYPE 
                                WHEN 'varchar' THEN 0
                                WHEN 'nvarchar' THEN 0
                                WHEN 'char' THEN 0
                                ELSE 1 END)

    SET @SQL='SELECT '''+@TABLE_CATALOG+''' catalog_name, '''+@TABLE_SCHEMA+''' schema_name, '''+@TABLE_NAME+''' table_name, '''+@COLUMN_NAME+''' column_name, '''+@DATA_TYPE+''' data_type, ' + 
            +' ['+@COLUMN_NAME+']'+
            +', * '
            +' FROM '+@TABLE_CATALOG+'.'+@TABLE_SCHEMA+'.'+@TABLE_NAME +
            +' WHERE ' + CASE WHEN @SHOULD_CAST=1 THEN 'CAST(['+@COLUMN_NAME + '] as NVARCHAR(max)) ' ELSE ' ['+@COLUMN_NAME + '] ' END 
            +' LIKE '''+ @SEARCH_VALUE_LIKE + ''' '

    PRINT @SQL;

    EXEC(@SQL)

    FETCH NEXT FROM col_cur INTO @TABLE_CATALOG, @TABLE_SCHEMA, @TABLE_NAME, @COLUMN_NAME, @DATA_TYPE;
    SET @i=@i+1
    -- IF @i > 10
    --  BREAK
END   
CLOSE col_cur;  
DEALLOCATE col_cur;

Несколько упоминаний об этом:

  • он использует курсоры вместо блокировки во время цикла
  • он может печатать прогресс (раскомментируйте при необходимости)
  • он может выйти после нескольких попыток (раскомментируйте IF в конце)
  • он отображает все записи
  • вы можете настроить его по мере необходимости

ОТКАЗ ОТ ОТВЕТСТВЕННОСТИ:

  • НЕ запускайте его в производственной среде!
  • МЕДЛЕННО.Если к БД обращаются другие службы / пользователи, ПОЖАЛУЙСТА, добавьте «WITH (NOLOCK)» после каждого имени таблицы во всех выборках, особенно динамических выборках.
  • Он не проверяет / не защищает от всех видовПараметры SQL-инъекций.
  • Если ваша БД огромна, приготовьтесь к сну, убедитесь, что запрос не будет завершен через несколько минут.
  • Он преобразует некоторые значения в строку, включая целые числа/ bigints / smallints / tinyints.Если они вам не нужны, поместите их в те же списки исключений с метками времени в верхней части скрипта.

Надеюсь, это поможет.

2 голосов
/ 21 ноября 2014

Это будет искать строку в каждой базе данных:

declare @search_term varchar(max)
set @search_term = 'something'

select @search_term = 'use ? SET QUOTED_IDENTIFIER ON
select
    ''[''+db_name()+''].[''+c.name+''].[''+b.name+'']'' as [object],
    b.type_desc as [type],
    d.obj_def.value(''.'',''varchar(max)'') as [definition]
from (
    select distinct
        a.id
    from sys.syscomments a
    where a.[text] like ''%'+@search_term+'%''
) a
inner join sys.all_objects b
    on b.[object_id] = a.id
inner join sys.schemas c
    on c.[schema_id] = b.[schema_id]
cross apply (
    select
        [text()] = a1.[text]
    from sys.syscomments a1
    where a1.id = a.id
    order by a1.colid
    for xml path(''''), type
) d(obj_def)
where c.schema_id not in (3,4) -- avoid searching in sys and INFORMATION_SCHEMA schemas
    and db_id() not in (1,2,3,4) -- avoid sys databases'

if object_id('tempdb..#textsearch') is not null drop table #textsearch
create table #textsearch
(
    [object] varchar(300),
    [type] varchar(300),
    [definition] varchar(max)
)

insert #textsearch
exec sp_MSforeachdb @search_term

select *
from #textsearch
order by [object]
...