Search all databases for value

后端 未结 4 1103
广开言路
广开言路 2020-12-16 08:22

Consider have a table like named : People

| Id    | Name    | Code   |
| 1     | John    | 857    |
| 2     | Mike    | 893    |
| 3     | Sara          


        
相关标签:
4条回答
  • 2020-12-16 08:59

    you can use this Store Procedure

        CREATE PROCEDURE dbo.SearchAllDatabases
      @SearchTerm NVARCHAR(255) = NULL
    AS
    BEGIN
      SET NOCOUNT ON;
      SET TRANSACTION ISOLATION LEVEL READ UNCOMMITTED;
    
      IF @SearchTerm IS NULL OR @SearchTerm NOT LIKE N'%[^%^_]%'
      BEGIN
        RAISERROR(N'Please enter a valid search term.', 11, 1);
        RETURN;
      END
    
      CREATE TABLE #results
      (
        [database]   SYSNAME,
        [schema]     SYSNAME,
        [table]      SYSNAME, 
        [column]     SYSNAME,
        ExampleValue NVARCHAR(1000)
      );
    
      DECLARE
        @DatabaseCommands  NVARCHAR(MAX) = N'', 
        @ColumnCommands    NVARCHAR(MAX) = N'';
    
      SELECT @DatabaseCommands = @DatabaseCommands + N'
        EXEC ' + QUOTENAME(name) + '.sys.sp_executesql 
            @ColumnCommands, N''@SearchTerm NVARCHAR(MAX)'', @SearchTerm;'
        FROM sys.databases 
        WHERE database_id  > 4  -- non-system databases  
          AND [state]      = 0  -- online 
          AND user_access  = 0; -- multi-user
    
        SET @ColumnCommands = N'DECLARE @q NCHAR(1),
              @SearchCommands NVARCHAR(MAX);
    
        SELECT @q = NCHAR(39), 
          @SearchCommands = N''DECLARE @VSearchTerm VARCHAR(255) = @SearchTerm;'';
    
        SELECT @SearchCommands = @SearchCommands + CHAR(10) + N''
    
          SELECT TOP (1)
            [db]     = DB_NAME(),
            [schema] = N'' + @q + s.name + @q + '', 
            [table]  = N'' + @q + t.name + @q + '',
            [column] = N'' + @q + c.name + @q + '',
            ExampleValue = LEFT('' + QUOTENAME(c.name) + '', 1000) 
          FROM '' + QUOTENAME(s.name) + ''.'' + QUOTENAME(t.name) + ''
          WHERE '' + QUOTENAME(c.name) + N'' LIKE @'' + CASE 
            WHEN c.system_type_id IN (35, 167, 175) THEN ''V'' 
            ELSE '''' END + ''SearchTerm;'' 
    
        FROM sys.schemas AS s
        INNER JOIN sys.tables AS t
        ON s.[schema_id] = t.[schema_id]
        INNER JOIN sys.columns AS c
        ON t.[object_id] = c.[object_id]
        WHERE c.system_type_id IN (35, 99, 167, 175, 231, 239)
          AND c.max_length >= LEN(@SearchTerm);
    
        PRINT @SearchCommands;
        EXEC sys.sp_executesql @SearchCommands, 
          N''@SearchTerm NVARCHAR(255)'', @SearchTerm;';
    
      INSERT #Results
      (
        [database],
        [schema],
        [table],
        [column],
        ExampleValue
      )
      EXEC [master].sys.sp_executesql @DatabaseCommands, 
        N'@ColumnCommands NVARCHAR(MAX), @SearchTerm NVARCHAR(255)', 
        @ColumnCommands, @SearchTerm;
    
      SELECT [Searched for] = @SearchTerm;
    
      SELECT [database],[schema],[table],[column],ExampleValue 
        FROM #Results 
        ORDER BY [database],[schema],[table],[column];
    END
    GO
    
    0 讨论(0)
  • 2020-12-16 09:14

    This seems like a crazy thing to do - the search could completely kill your server. That said, if this is a one-off/occasional use manual run kind of thing then you can create a script to generate the SQL commands you need and then execute the result sets. I've done this sort of thing before to refactor columns in a database. Your script would need to first run a query to get the names of all the DBs on your sql-server instance

      SELECT * FROM sys.databases
    

    Then create dynamic sql including the USE command to specify the DB and use the information_schema.tables and .columns to get the names of all the tables and columns you want to search - up to you how you decided to select the columns to be searched (is it just columns like N'%name%' for example.

    Then use this information in a for loop to create individual table/column searches. For efficiency (and to help you debug if it's not working) I suggest utilise @table variables.

    Finally select the contents of any @tables holding the table queries you've created.

    This output can then be run on the server - providing you've included the use commands or prefixed table names with [dbname].[schema].

    0 讨论(0)
  • 2020-12-16 09:17
    SELECT * FROM all_objects where object_name = 'XXXX';
    
    0 讨论(0)
  • 2020-12-16 09:22

    I have updated your Logic as per below and it works fine, please have a look:

    DECLARE @SearchStr VARCHAR(50)='Surat'
    
    DECLARE @Results TABLE(DatabaseName NVARCHAR(500),  TableName nvarchar(370),ColumnName nvarchar(370), ColumnValue nvarchar(3630),PrimaryKey nvarchar(200), PrimaryKeyValue nvarchar(4000))
    
    SET NOCOUNT ON
    
    DECLARE @TableList AS Table
    (
        TableName VARCHAR(500),
        RowNo INT
    )
    
    DECLARE @ColumnList AS Table
    (
        ColumnName VARCHAR(500),
        RowNo INT
    )
    
    DECLARE @PrimaryKeyList AS Table
    (
        PrimaryKeyName VARCHAR(500)
    )
    
    DECLARE @TableName nvarchar(256), @ColumnName nvarchar(128), @SearchStr2 nvarchar(110), @PrimaryKey nvarchar(200), @CurrentTableName nvarchar(256)
    SET @TableName = ''
    SET @SearchStr2 = QUOTENAME('%' + @SearchStr + '%', '''')
    
    DECLARE @DatabaseCount INT=0, @Index INT=0, @DatabaseName NVARCHAR(500), @TotalColumnCount INT, @ColumnIndex INT=0, @TotalTableCount INT, @TableIndex INT=0
    
    SELECT 
        *,
        ROW_NUMBER() OVER (ORDER BY name) AS RowNo 
    INTO #tblDatabases 
    FROM Sys.Databases
    WHERE name NOT IN ('master','model','msdb','tempdb')
    
    SELECT @DatabaseCount=COUNT (*) FROM #tblDatabases
    WHILE @Index<@DatabaseCount
    BEGIN
        SET @Index=@Index+1
        SELECT @DatabaseName='',@TableIndex=0,@ColumnIndex=0,@TableName='',@ColumnName=''
        SELECT @DatabaseName=name FROM #tblDatabases WHERE RowNo=@Index     
    
        DELETE FROM @TableList
        INSERT INTO @TableList
        EXEC('
                SELECT QUOTENAME(TABLE_SCHEMA) + ''.'' + QUOTENAME(TABLE_NAME),
                    ROW_NUMBER() OVER (ORDER BY TABLE_NAME)
                FROM ['+@DatabaseName+'].INFORMATION_SCHEMA.TABLES
                WHERE TABLE_TYPE = ''BASE TABLE''
            ')
    
        SELECT @TotalTableCount=COUNT(*) FROM @TableList
    
        WHILE @TableIndex<@TotalTableCount 
        BEGIN   
    
            SET @TableIndex=@TableIndex+1
            SELECT @ColumnName = '',@ColumnIndex=0
    
            SELECT @TableName=TableName FROM @TableList  WHERE RowNo=@TableIndex            
            SET @CurrentTableName=REPLACE(REPLACE(REPLACE(@TableName,'[dbo].',''),'[',''),']','')
    
            DELETE FROM @ColumnList
            INSERT INTO @ColumnList
            EXEC('SELECT
                    COLUMN_NAME,ROW_NUMBER() OVER (ORDER BY COLUMN_NAME)
                        FROM ['+@DatabaseName+'].INFORMATION_SCHEMA.COLUMNS
                    WHERE TABLE_SCHEMA = PARSENAME('''+@TableName+''', 2)
                        AND TABLE_NAME = PARSENAME('''+@TableName+''', 1)
                        AND DATA_TYPE IN (''char'', ''varchar'', ''nchar'', ''nvarchar'')
    
    
            ')
    
            SELECT @TotalColumnCount=COUNT(*) FROM @ColumnList
    
            WHILE @ColumnIndex<@TotalColumnCount
            BEGIN
                SET @ColumnIndex=@ColumnIndex+1
                SET @ColumnName=''
                SELECT @ColumnName=ColumnName FROM @ColumnList WHERE RowNo=@ColumnIndex         
    
                DELETE FROM @PrimaryKeyList
                INSERT INTO @PrimaryKeyList
                EXEC('
                        SELECT Col.Column_Name from 
                            ['+@DatabaseName+'].INFORMATION_SCHEMA.TABLE_CONSTRAINTS Tab, 
                            ['+@DatabaseName+'].INFORMATION_SCHEMA.CONSTRAINT_COLUMN_USAGE Col 
                        WHERE 
                            Col.Constraint_Name = Tab.Constraint_Name
                            AND Col.Table_Name = Tab.Table_Name
                            AND Constraint_Type = ''PRIMARY KEY''
                            AND Col.Table_Name= '''+@CurrentTableName+'''           
                    ')
    
                SELECT @PrimaryKey=''
                SELECT @PrimaryKey=PrimaryKeyName FROM @PrimaryKeyList
                SET @PrimaryKey=ISNULL(@PrimaryKey,'')
    
                IF @ColumnName IS NOT NULL AND @PrimaryKey<>''
                BEGIN   
                    INSERT INTO @Results
                    EXEC
                    (
                        'SELECT '''+@DatabaseName+''','''+@CurrentTableName+''',''' + @ColumnName + ''', LEFT(' + @ColumnName + ', 3630) , '''+@PrimaryKey+''', [' + @PrimaryKey + '] 
                        FROM ['+@DatabaseName+'].' + @TableName + ' (NOLOCK) ' +
                        ' WHERE ' + @ColumnName + ' LIKE ' + @SearchStr2
                    )
                END
            END
        END
    END
    
    
    SELECT ROW_NUMBER() OVER (ORDER BY DatabaseName) AS Id,DatabaseName,TableName,ColumnName, ColumnValue AS SearchValue,PrimaryKeyValue AS Pk, PrimaryKey  FROM @Results
    
    DROP TABLE #tblDatabases
    
    0 讨论(0)
提交回复
热议问题