2012-02-07 58 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

它將搜索每個表,讓你在找到字符串多少次每桌!

相關問題