2012-02-07 87 views
75

我知道这是可能的,但不知道如何。如何搜索sql server数据库的字符串?

我需要搜索Microsoft SQL数据库中所有提到的特定字符串。 例如:我想搜索字符串“tblEmployes”的所有表,视图,函数,存储过程...。 (不是表格中的数据)

我需要这个的原因之一,我想删除一些额外的数据表创建,但我担心他们也许在程序或函数的某个地方使用。

任何帮助表示赞赏。

+3

[redgate sql search](http://www.red-gate.com/products/sql-development/sql-search/) – 2012-02-08 06:04:57

+0

希望这会帮助别人,http://stackoverflow.com/questions/13174627/searching-text-from-db-sql-server/22854200#22854200 – NoNaMe 2014-05-27 04:09:33

回答

15

在SQL Server中得到一个表的名字:

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%' 
+0

这个查询只搜索对象。我们需要在所有现有表格中搜索一个字符串。 – 2017-04-25 21:29:55

97

这将搜索特定数据库中每个表的每一列。要在搜索数据库上创建存储过程

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 

工作得非常好!

+0

第二个参数“exactMatch = 0”是什么意思? – 2015-07-13 14:05:40

+0

如果你看一下脚本,它只是一个早期检查case语句的参数,用于决定是使用“value”还是“%value%”来搜索字符串。 – Chizzle 2015-09-17 14:34:26

+2

这只返回找到的第一个结果,没有其他结果。有没有办法让它返回数据库中字符串的所有实例? – qroberts 2016-01-21 19:23:49

3

你可以;

  1. 脚本的数据库到一个文件,然后搜索使用文本编辑器 的tblEmployees文件。在SQL Server管理工具(SSMS)中,右键单击数据库并选择生成脚本。
  2. 使用SSMS“查看依赖关系”通过右键单击在tblEmployees,看看哪些其他对象是依赖于它
  3. 使用免费的第三方工具,如展鹏SQLSearch按关键字搜索按名称和内容的所有数据库对象。
+0

#1听起来不错。我只是不能在服务器上运行它,因为我没有访问权限。 – bobetko 2012-02-08 14:27:31

+0

谢谢。不知道为什么有人给你-1。我修正了这一点。试过RedGate ......完全符合我的要求。 – bobetko 2012-02-08 14:40:39

53

如果你需要按名称查找数据库对象(如表,列,触发器) - 看看所谓SQL Search免费红门工具,它做到这一点 - 它搜索整个数据库的任何种类的字符串。

enter image description here

enter image description here

这是一个伟大的必须具备的任何DBA或数据库开发人员工具 - 为什么我已经提到它的绝对免费用于任何用途的?

+19

很好的工具,但它不会搜索表格中的字符串 – JGilmartin 2013-06-03 08:37:15

+0

不适用于我。我正在使用Sql Azure。 – 2013-10-24 13:18:09

+2

不搜索实际行 – LearningJrDev 2015-09-04 19:26:34

10

您可以将您的数据库(如果很小)导出到硬盘驱动器/桌面,然后通过文本编辑器进行字符串搜索。

+5

这实际上不是一个坏主意。 – 2013-03-20 20:33:31

+0

:)你也可以使用脚本。但一个好的文本编辑器几乎可以做任何你需要的SQL代码。 – 2013-03-21 07:29:37

+0

哪个文本编辑器会很乐意载入很多GB的数据? – Bohdan 2016-04-22 22:11:08

41

您也可以尝试ApexSQL Search - 这是一个免费的SSMS添加类似于SQL搜索。

如果你真的想只使用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] 
+4

ApexSQL Search非常棒。使用此工具无需使用脚本。 – Mike 2016-06-30 20:00:03

+1

这是一个很棒的帮助伴侣。感谢它:D – miniGweek 2016-12-01 06:27:39

+1

此查询只搜索对象。我们需要在所有现有表格中搜索一个字符串。 – 2017-04-25 21:29:08

2

这将为字符串搜索过的每个数据库:

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 ''%'[email protected]_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] 
-3

假如你不会做公共搜索整个数据库,你只是想自己找一个关键字,这是最简单,更清洁,更快速的解决方案。

  1. 将数据库转储到文件。

    $ mysqldump -u root -p your_database > your_database.sql 
    
  2. 请在文件

    $ grep 'keyword' your_database.sql 
    

一个grep和你就大功告成了。

+3

“Microsoft SQL服务器”而不是MySQL – HEDMON 2016-09-02 05:14:06

+0

我最近从@marc_s得知MS SQL导出是二进制文件,因此无法使用您建议的方法导出,读取或搜索。 – 2017-06-06 21:45:50

5

此代码搜索程序和功能,但在表:)不是搜索

SELECT name FROM sys.all_objects WHERE Object_definition(object_id) LIKE '%text%' ORDER BY name 
1

老问题,我知道,但在这里不用我的版本... 我把它命名为“大海捞针”的明显原因。

它搜索每行和每列中特定值,而不是列名等

执行搜索(对于当然前两个变量替换值):

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 [email protected]_DB AND DATA_TYPE NOT IN ('timestamp', 'datetime'); 

DECLARE @TOTAL int = (SELECT COUNT(*) 
FROM information_schema.columns WHERE [email protected]_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+'.'[email protected]_SCHEMA+'.'[email protected]_NAME+': '[email protected]_NAME+' ('[email protected]_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 '''[email protected]_CATALOG+''' catalog_name, '''[email protected]_SCHEMA+''' schema_name, '''[email protected]_NAME+''' table_name, '''[email protected]_NAME+''' column_name, '''[email protected]_TYPE+''' data_type, ' + 
      +' COUNT(['[email protected]_NAME+']) records '+ 
      +' FROM '[email protected]_CATALOG+'.'[email protected]_SCHEMA+'.'[email protected]_NAME + 
      +' WHERE ' + CASE WHEN @SHOULD_CAST=1 THEN 'CAST(['[email protected]_NAME + '] as NVARCHAR(max)) ' ELSE ' ['[email protected]_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 @[email protected]+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'%@[email protected]%' 
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 '''[email protected]_CATALOG+''' catalog_name, '''[email protected]_SCHEMA+''' schema_name, '''[email protected]_NAME+''' table_name, '''[email protected]_NAME+''' column_name, '''[email protected]_TYPE+''' data_type, ' + 
      +' ['[email protected]_NAME+']'+ 
      +', * ' 
      +' FROM '[email protected]_CATALOG+'.'[email protected]_SCHEMA+'.'[email protected]_NAME + 
      +' WHERE ' + CASE WHEN @SHOULD_CAST=1 THEN 'CAST(['[email protected]_NAME + '] as NVARCHAR(max)) ' ELSE ' ['[email protected]_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 @[email protected]+1 
    -- IF @i > 10 
    -- BREAK 
END 
CLOSE col_cur; 
DEALLOCATE col_cur; 

很少提到这件事:

  • 它使用的,而不是阻塞游标while循环(如果需要取消注释)
  • 它可以打印进度
  • 尝试几次后,可以退出(取消注释IF末)
  • 它会显示所有记录
  • 您可以微调它需要

免责声明:

  • 请勿在生产环境中运行它!
  • 它很慢。如果数据库被其他服务/用户访问,请在所有选择中的每个表名之后添加“WITH(NOLOCK)”,特别是动态选择的名称。
  • 它不验证/防范各种SQL注入选项。
  • 如果您的数据库很大,请准备好自己进行一些睡眠,确保查询在几分钟后不会被杀死。
  • 它将一些值转换为字符串,包括ints/bigints/smallints/tinyints。如果您不需要这些内容,请将它们放在同一个排除列表中,并在脚本顶部添加时间戳。

希望这会有所帮助。

0

被赋予访问数据库,而不是在我的查询是被存储在表中。

通过@marc_s回答启发,我看了一下HeidiSQL这是一个Windows程序,它可以处理的MySQL, MSSQL和PostgreSQL。

发现它也可以搜索数据库中的字符串。

Click Search, then Find text on Server

Search tool open. Make sure the DB is selected

它将搜索每个表,让你在找到字符串多少次每桌!

相关问题