Tuesday, September 29, 2015

Searching all Fields in all Tables in all Databases in SQL Server

Sometimes you just want to push the limits of what you think you can do with a particular technology.  This was one of those times.  I wanted to see if there was an easy way to search every field in every table in every database on a server for a particular value.  Here's what I came up with.  Before anyone goes crazy (if anyone is actually reading this), I copied bits from built-in stored procedures SP_MSFOREACHDB and SP_MSFOREACH_WORKER to make this work.

I really don't like building the dynamic SQL like this, but it did get the job done so I guess I can't really complain about it.

DECLARE
     @DatabaseName NVARCHAR(517)
    ,@SearchText NVARCHAR(1000) = 'Some value'

DECLARE DatabaseCursor CURSOR GLOBAL FOR
SELECT [name]
FROM master.dbo.sysdatabases d
WHERE
    d.[status] &292 = 0
    AND DATABASEPROPERTY(d.[name], 'issingleuser') = 0
    AND HAS_DBACCESS(d.[name]) = 1
    AND [name] NOT IN ('master''model''msdb''tempdb')

OPEN DatabaseCursor
FETCH NEXT FROM DatabaseCursor INTO @DatabaseName

WHILE @@FETCH_STATUS = 0
BEGIN

    DECLARE @SQL NVARCHAR(MAX)

    SET @SQL = N'USE ' N'[' + @DatabaseName + N'] '
    SET @SQL = @SQL + N'DECLARE @SchemaName NVARCHAR(256), @TableName NVARCHAR(256), @ColumnName NVARCHAR(256) '
    SET @SQL = @SQL + N'DECLARE TableCursor CURSOR FOR '
    SET @SQL = @SQL + N'SELECT sch.[Name] AS SchemaName, st.[Name] AS TableName, sc.[Name] AS ColumnName FROM sys.tables st WITH (NOLOCK) INNER JOIN sys.columns sc WITH (NOLOCK) ON st.object_id = sc.object_id INNER JOIN sys.schemas sch WITH (NOLOCK) ON st.schema_id = sch.schema_id '
    SET @SQL = @SQL + N'OPEN TableCursor FETCH NEXT FROM TableCursor INTO @SchemaName, @TableName, @ColumnName '
    SET @SQL = @SQL + N'WHILE @@FETCH_STATUS = 0 BEGIN '
    SET @SQL = @SQL + N'DECLARE @InternalSQL NVARCHAR(MAX) = ''SELECT @CountParam = COUNT(*) FROM ['' + @SchemaName + ''].['' + @TableName + ''] WHERE ['' + @ColumnName + ''] LIKE ''''%' + @SearchText + '%'''''' '
    SET @SQL = @SQL + N'DECLARE @Count INT '
    SET @SQL = @SQL + N'EXEC SP_EXECUTESQL @InternalSQL, N''@CountParam INT OUT'', @Count OUT '
    SET @SQL = @SQL + N'IF (@Count > 0) '
    SET @SQL = @SQL + N'BEGIN '
    SET @SQL = @SQL + N'PRINT @SchemaName + ''.'' + @TableName + ''.'' + @ColumnName '
    SET @SQL = @SQL + N'END '
    SET @SQL = @SQL + N'FETCH NEXT FROM TableCursor INTO @SchemaName, @TableName, @ColumnName '
    SET @SQL = @SQL + N'END '
    SET @SQL = @SQL + N'CLOSE TableCursor '
    SET @SQL = @SQL + N'DEALLOCATE TableCursor '

    EXEC (@SQL)

    FETCH NEXT FROM DatabaseCursor INTO @DatabaseName

END

CLOSE DatabaseCursor
DEALLOCATE DatabaseCursor

No comments:

Post a Comment