Find a value anywhere in a database

前端 未结 18 881
小蘑菇
小蘑菇 2020-11-22 03:52

Given a #, how do I discover in what table and column it could be found within?

I don\'t care if it\'s fast, it just needs to work.

相关标签:
18条回答
  • 2020-11-22 03:57

    This might help you. - from Narayana Vyas. It searches all columns of all tables in a given database. I have used it before and it works.

    This is the Stored Proc from the above link - the only change I made was substituting the temp table for a table variable so you don't have to remember to drop it each time.

    CREATE PROC SearchAllTables
    (
        @SearchStr nvarchar(100)
    )
    AS
    BEGIN
    
    -- Copyright © 2002 Narayana Vyas Kondreddi. All rights reserved.
    -- Purpose: To search all columns of all tables for a given search string
    -- Written by: Narayana Vyas Kondreddi
    -- Site: http://vyaskn.tripod.com
    -- Tested on: SQL Server 7.0 and SQL Server 2000
    -- Date modified: 28th July 2002 22:50 GMT
    
    DECLARE @Results TABLE(ColumnName nvarchar(370), ColumnValue nvarchar(3630))
    
    SET NOCOUNT ON
    
    DECLARE @TableName nvarchar(256), @ColumnName nvarchar(128), @SearchStr2 nvarchar(110)
    SET  @TableName = ''
    SET @SearchStr2 = QUOTENAME('%' + @SearchStr + '%','''')
    
    WHILE @TableName IS NOT NULL
    BEGIN
        SET @ColumnName = ''
        SET @TableName = 
        (
            SELECT MIN(QUOTENAME(TABLE_SCHEMA) + '.' + QUOTENAME(TABLE_NAME))
            FROM    INFORMATION_SCHEMA.TABLES
            WHERE       TABLE_TYPE = 'BASE TABLE'
                AND QUOTENAME(TABLE_SCHEMA) + '.' + QUOTENAME(TABLE_NAME) > @TableName
                AND OBJECTPROPERTY(
                        OBJECT_ID(
                            QUOTENAME(TABLE_SCHEMA) + '.' + QUOTENAME(TABLE_NAME)
                             ), 'IsMSShipped'
                               ) = 0
        )
    
        WHILE (@TableName IS NOT NULL) AND (@ColumnName IS NOT NULL)
        BEGIN
            SET @ColumnName =
            (
                SELECT MIN(QUOTENAME(COLUMN_NAME))
                FROM    INFORMATION_SCHEMA.COLUMNS
                WHERE       TABLE_SCHEMA    = PARSENAME(@TableName, 2)
                    AND TABLE_NAME  = PARSENAME(@TableName, 1)
                    AND DATA_TYPE IN ('char', 'varchar', 'nchar', 'nvarchar')
                    AND QUOTENAME(COLUMN_NAME) > @ColumnName
            )
    
            IF @ColumnName IS NOT NULL
            BEGIN
                INSERT INTO @Results
                EXEC
                (
                    'SELECT ''' + @TableName + '.' + @ColumnName + ''', LEFT(' + @ColumnName + ', 3630) 
                    FROM ' + @TableName + ' (NOLOCK) ' +
                    ' WHERE ' + @ColumnName + ' LIKE ' + @SearchStr2
                )
            END
        END 
    END
    
    SELECT ColumnName, ColumnValue FROM @Results
    END
    
    0 讨论(0)
  • 2020-11-22 03:58

    It's my way to resolve this question. Tested on SQLServer2008R2

    CREATE PROC SearchAllTables
    @SearchStr nvarchar(100)
    AS
    BEGIN
    DECLARE @dml nvarchar(max) = N''        
    IF OBJECT_ID('tempdb.dbo.#Results') IS NOT NULL DROP TABLE dbo.#Results
    CREATE TABLE dbo.#Results
     ([tablename] nvarchar(100), 
      [ColumnName] nvarchar(100), 
      [Value] nvarchar(max))  
    SELECT @dml += ' SELECT ''' + s.name + '.' + t.name + ''' AS [tablename], ''' + 
                    c.name + ''' AS [ColumnName], CAST(' + QUOTENAME(c.name) + 
                   ' AS nvarchar(max)) AS [Value] FROM ' + QUOTENAME(s.name) + '.' + QUOTENAME(t.name) +
                   ' (NOLOCK) WHERE CAST(' + QUOTENAME(c.name) + ' AS nvarchar(max)) LIKE ' + '''%' + @SearchStr + '%'''
    FROM sys.schemas s JOIN sys.tables t ON s.schema_id = t.schema_id
                       JOIN sys.columns c ON t.object_id = c.object_id
                       JOIN sys.types ty ON c.system_type_id = ty.system_type_id AND c .user_type_id = ty .user_type_id
    WHERE t.is_ms_shipped = 0 AND ty.name NOT IN ('timestamp', 'image', 'sql_variant')
    
    INSERT dbo.#Results
    EXEC sp_executesql @dml
    
    SELECT *
    FROM dbo.#Results
    END
    
    0 讨论(0)
  • 2020-11-22 03:58

    Database client tools (like DBeaver or phpMyAdmin) often support means of fulltext search through entire database.

    0 讨论(0)
  • 2020-11-22 04:00

    I optimized Allain Lalonde answer (https://stackoverflow.com/a/436676/412368). Numeric values are still supported. Should be roughly 4-5 times faster (1:03 vs 4:30), tested on a desktop with a 7GB database. http://developer.azurewebsites.net/2015/01/mssql-searchalltables/

    IF OBJECT_ID ('dbo.SearchAllTables', 'P') IS NOT NULL 
        DROP PROCEDURE dbo.SearchAllTables;
    GO
    
    CREATE PROC SearchAllTables 
    (
        @SearchStr nvarchar(100)
    )
    AS
    BEGIN
    
    -- Copyright © 2002 Narayana Vyas Kondreddi. All rights reserved.
    -- Purpose: To search all columns of all tables for a given search string
    -- Written by: Narayana Vyas Kondreddi
    -- Site: http://vyaskn.tripod.com
    -- Customized and modified: 2014-01-21
    -- Tested on: SQL Server 2008 R2
    
    DECLARE @Results TABLE(ColumnName nvarchar(370), ColumnValue nvarchar(3630))
    
    SET NOCOUNT ON
    
    DECLARE @TableName nvarchar(256)
    DECLARE @ColumnName nvarchar(128)
    DECLARE @DataType nvarchar(128)
    
    DECLARE @SearchStr2 nvarchar(110)
    DECLARE @SearchDecimal decimal(38,19)
    DECLARE @Query nvarchar(4000)
    SET @SearchStr2 = QUOTENAME('%' + @SearchStr + '%', '''')
    SET @SearchDecimal = CASE WHEN ISNUMERIC(@SearchStr) = 1 THEN CONVERT(decimal(38,19), @SearchStr) ELSE NULL END
    PRINT '@SearchStr2: ' + @SearchStr2
    PRINT '@SearchDecimal: ' + CAST(@SearchDecimal AS nvarchar)
    
    SET @TableName = ''
    WHILE @TableName IS NOT NULL
    BEGIN
        SET @ColumnName = ''
        SET @TableName = 
        (
            SELECT MIN(QUOTENAME(TABLE_SCHEMA) + '.' + QUOTENAME(TABLE_NAME))
            FROM    INFORMATION_SCHEMA.TABLES
            WHERE       TABLE_TYPE = 'BASE TABLE'
                AND QUOTENAME(TABLE_SCHEMA) + '.' + QUOTENAME(TABLE_NAME) > @TableName
                AND OBJECTPROPERTY(
                        OBJECT_ID(
                            QUOTENAME(TABLE_SCHEMA) + '.' + QUOTENAME(TABLE_NAME)
                             ), 'IsMSShipped'
                               ) = 0
        )
    
        WHILE (@TableName IS NOT NULL) AND (@ColumnName IS NOT NULL)
        BEGIN
            SET @ColumnName =
            (
                SELECT MIN(QUOTENAME(COLUMN_NAME))
                        DATA_TYPE
                FROM    INFORMATION_SCHEMA.COLUMNS
                WHERE       TABLE_SCHEMA    = PARSENAME(@TableName, 2)
                    AND TABLE_NAME  = PARSENAME(@TableName, 1)
                    AND DATA_TYPE IN ('char', 'varchar', 'nchar', 'nvarchar',
                                      'int', 'bigint', 'tinyint', 'numeric', 'decimal')
                    AND QUOTENAME(COLUMN_NAME) > @ColumnName
            )
            SET @DataType =
            (
                SELECT DATA_TYPE
                FROM    INFORMATION_SCHEMA.COLUMNS
                WHERE       TABLE_SCHEMA    = PARSENAME(@TableName, 2)
                    AND TABLE_NAME  = PARSENAME(@TableName, 1)
                    AND QUOTENAME(COLUMN_NAME) = @ColumnName
            )
            PRINT @TableName + '.' + @ColumnName + ' (' + @DataType + ')'
    
            IF @ColumnName IS NOT NULL
            BEGIN
                IF @DataType IN ('int', 'bigint', 'tinyint', 'numeric', 'decimal')
                BEGIN
                    IF @SearchDecimal IS NOT NULL
                    BEGIN
                        SET @Query = 'SELECT ''' + @TableName + '.' + @ColumnName + ''', LEFT(CAST(' + @ColumnName + ' AS nvarchar(110)), 3630) ' +
                                     'FROM ' + @TableName + ' (NOLOCK) ' +
                                     ' WHERE ' + @ColumnName + ' = ' + CAST(@SearchDecimal AS nvarchar)
                        PRINT '    ' + @Query
                        INSERT INTO @Results
                        EXEC (@Query)
                    END
                END
                ELSE
                BEGIN
                    SET @Query = 'SELECT ''' + @TableName + '.' + @ColumnName + ''', LEFT(' + @ColumnName + ', 3630) ' +
                                 'FROM ' + @TableName + ' (NOLOCK) ' +
                                 ' WHERE ' + @ColumnName + ' LIKE ' + @SearchStr2
                    PRINT '    ' + @Query
                    INSERT INTO @Results
                    EXEC (@Query)
                END
            END
        END 
    END
    
    SELECT ColumnName, ColumnValue FROM @Results
    END
    
    0 讨论(0)
  • 2020-11-22 04:00

    I wrote once a tool for myself to do exactly that thing:

    a7 SqlTools

    It's free and open-source:

    github link

    0 讨论(0)
  • 2020-11-22 04:01

    Suppose if you want to get all the table with name a column name contain logintime in the database MyDatabase below is the code sample

        use MyDatabase
    
        SELECT t.name AS table_name,
        SCHEMA_NAME(schema_id) AS schema_name,
        c.name AS column_name
        FROM sys.tables AS t
        INNER JOIN sys.columns c ON t.OBJECT_ID = c.OBJECT_ID
        WHERE c.name LIKE '%logintime%'
        ORDER BY schema_name, table_name;
    
    0 讨论(0)
提交回复
热议问题