Thursday, October 12, 2006

Search MS SQL Server for any text

When you know little about a database or can't remember it is often nice to be able to do global type searches on that database. This scenario can be thought of in two ways.
  • Search database schema
  • Search database data

Below I describe how to do both on a MS SQL database.

Search database schema It has been my experience that when doing any kind of database analysis it is nice to know dependencies between objects. Yes, I know you can get dependencies of an object. But what if what you are looking for is cross-database or you want to search on part of name of an object. Below is a very simple, but effective stored procedure (thank you Michael Lyczywek): create proc SearchSchema(@QueryText as varchar(200)) as select distinct name from sysobjects a inner join syscomments b on a.id = b.id where text like '%' + @QueryText + '%' go For example let's say you have a person table in Database1 and you want to find all references in Database2 to the Person table. To do so you could do the following: SearchSchema 'Person' Search database data Often when I have been tasked with making a change in an application, I need to figure out where that is in the database. The following stored procedure allows you to search all columns of all tables for a given value. This has been taken directly from an article by Narayana Vyas Kondreddi.

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


 CREATE TABLE #Results (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

To use this stored procedure you would do something like the following: SearchAllTables 'Brent Vermilion'

7 comments:

sdfadadf said...

Thanks, worked :)

Brent V said...

Mindaugas,
Glad to hear it worked. Thanks for the feedback.

Brent

Anonymous said...

Many thanks; worked well on 2005 server;
for other newbees like me:

click on "New Query"

Paste the code ; then click Execute

Then again: "New Query"

type:
exec SearchAllTables "thewordyouwanttolookfor"

Anonymous said...

great, works on a db with several million records. Took me some time though

Unknown said...

to search ntext and text fields

switch this line:
AND DATA_TYPE IN ('char', 'varchar', 'nchar', 'nvarchar')

to this:
AND DATA_TYPE IN ('char', 'varchar', 'nchar', 'nvarchar', 'text', 'ntext')

and this line:
'SELECT ''' + @TableName + '.' + @ColumnName + ''', LEFT(' + @ColumnName + ', 3630)

to this:
'SELECT ''' + @TableName + '.' + @ColumnName + ''', LEFT(CAST(' + @ColumnName + ' AS NVARCHAR(4000) ), 3630)

金大衛 said...

very useful and inspiring, thanks ;)

Unknown said...

very usefull!!!!!!!!