Search for column values in SQL Server database - sql-server

I want to find a specific data like Country name 'Spain' or any person name like 'John'
So is there any way to find which table's columns contain data Spain or John in a SQL Server database (remember these are not column Names, these are values stored in the columns)

Try below stored procedure, I found it here.
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

Create this stored procedure and pass the data which you want to find
/****** Object: StoredProcedure [dbo].[FindMyData_String] Script Date: 07/04/2012 12:58:59 ******/
SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO
Create PROCEDURE [dbo].[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

I wouldn’t bother with any complex stored procedures as long as I can use some of the free tools that already exist on the market. Just install any of these and you’ll get the job done a lot faster.
SSMS toolpack – searches only data. Free for all versions except 2012
ApexSQL Search – searches objects and data
There is also SQL Search from Red Gate but I never used it myself.

Related

T-SQL script to search for string in database and show table name and record

I have a script that will search a database for a string and list the table name and column. I need to get it to list not just the column but the whole record so I can compare accounts in text. How would I change the script to show the entire record and not just the column?
USE powercampustest
DECLARE #SearchStr nvarchar(100) = '93335' --Five,Test
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', 'int', 'decimal')
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
/*
ColumnName ColumnValue
[dbo].[ADDRESS].[PEOPLE_ORG_CODE_ID] P000092436
[dbo].[ADDRESS].[PEOPLE_ORG_ID] 000092436
[dbo].[ADDRESSHIERARCHYUNIQUE].[PEOPLE_ORG_CODE_ID] P000092436
[dbo].[ADDRESSSCHEDULE].[PEOPLE_ORG_CODE_ID] P000092436
[dbo].[ADDRESSSCHEDULE].[PEOPLE_ORG_CODE_ID] P000092436
[dbo].[ADDRESSSCHEDULE].[PEOPLE_ORG_CODE_ID] P000092436
[dbo].[ADDRESSSCHEDULE].[PEOPLE_ORG_CODE_ID] P000092436
[dbo].[ADDRESSSCHEDULE].[PEOPLE_ORG_ID] 000092436
[dbo].[ADDRESSSCHEDULE].[PEOPLE_ORG_ID] 000092436
[dbo].[ADDRESSSCHEDULE].[PEOPLE_ORG_ID] 000092436
First, the script you currently have is, well, kind of bad.
Loops are almost never the correct approach in SQL, nested loops are even worst.
Second, since you are searching all the tables in the database, your best option to get the entire row content is as XML. This will enable you to have a single table with only 3 columns to keep all the information you need: ColumnName, ColumnValue, and RowContent.
It will also enable you to go with a set based approach and loose the loops.
So first, you declare the search parameter and the variable that will hold your query:
DECLARE #SearchStr nvarchar(100) = 'P000092436',
#SQL nvarchar(max) = ''
Then, you use the built in views of Information_schema.Columns and Information_schema.Tables to create your query:
SELECT #SQL = #SQL +
'UNION
SELECT '''+ QUOTENAME(t.TABLE_SCHEMA) +'.'+ QUOTENAME(c.TABLE_NAME) +'.'+ QUOTENAME(c.COLUMN_NAME) +''' As ColumnName, -- This gets you the full column name
'''+ #SearchStr +''' As ColumnValue,
(SELECT * FROM '+ QUOTENAME(c.TABLE_NAME) +' WHERE '+ QUOTENAME(c.COLUMN_NAME) +' LIKE ''%'+ #SearchStr +'%'' FOR XML AUTO) -- This gets you the row content
FROM '+ QUOTENAME(c.TABLE_NAME) +'
WHERE '+ QUOTENAME(c.COLUMN_NAME) +' LIKE ''%'+ #SearchStr +'%''
'
FROM INFORMATION_SCHEMA.COLUMNS c
INNER JOIN INFORMATION_SCHEMA.TABLES t ON c.TABLE_NAME = t.TABLE_NAME
WHERE t.TABLE_TYPE = 'BASE TABLE'
Then, use STUFF to remove the first UNION:
SET #SQL = STUFF(#SQL, 1, 7, '')
No, the query this will create is something like this:
SELECT '[schema].[table1].[column1]' As ColumnName,
'P000092436' As ColumnValue,
(SELECT * FROM [table1] WHERE [column1] LIKE '%P000092436%' FOR XML AUTO)
FROM [table1]
WHERE [column1] LIKE '%P000092436%'
UNION
SELECT '[schema].[table1].[column2]' As ColumnName,
'P000092436' As ColumnValue,
(SELECT * FROM [table1] WHERE [column2] LIKE '%P000092436%' FOR XML AUTO)
FROM [table1]
WHERE [column2] LIKE '%P000092436%'
UNION....
Including all tables and all columns.
The next step is to create the temporary table to hold the results:
CREATE TABLE #SearchResults
(
ColumnName nvarchar(500),
ColumnValue nvarchar(100),
RowContent xml
)
and insert the result of this query into it:
INSERT INTO #SearchResults
EXEC(#SQL)
You can see a live demo on Rextester.

How to find tables and columns containing specified column value

In T-SQL is it possible to give me a list of tables and columns that contain specified column value?
For example, I get a employee report generated out of a SQL Server database that shows "John" as name in one of the columns. Now I want to find out where "John" appears as a field value in any table/column in the database.
So in English my query should sound like;
Select table, column
from database A
where field = 'John'
Thanks
Try with this procedure
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
#DataToFind='Enter Your String'

Find Replace All String Data in a SQL Server Database

I am looking for a script which finds and replaces all fields of type string within a DB with specified text.
The script would for example take the following parameters:
Search for: null
Replace with: empty-string
The primary string data types in SQL Server: Varchar, NVarchar, Text.
This script would then comb through all string based table data and look for in this case null and replace it with a empty string.
Ok I've put together the following code in the meantime.
-- Specify 'dbo' for all tables
DECLARE #schemaName VARCHAR(5) = 'dbo'
BEGIN
DECLARE #tableName VARCHAR(255) -- table name
DECLARE #tableID INT -- table id (aka syst.table.object_id)
DECLARE table_cursor CURSOR FOR
SELECT T.object_id AS TableID, T.name AS TableName FROM sys.tables T
INNER JOIN sys.schemas S ON S.schema_id = T.schema_id
WHERE S.name = #schemaName
OPEN table_cursor
FETCH NEXT FROM table_cursor INTO #tableID, #tableName
WHILE ##FETCH_STATUS = 0
BEGIN
-- construct each tables queries
DECLARE #totalColumnsFound INT = (SELECT COUNT(*) FROM sys.columns C WHERE OBJECT_ID = #tableID
-- text and nvarchar column data types chosen for me (if you need more like ntext, varcahr see sys.types for their ids)
AND (C.system_type_id = 35 OR c.system_type_id = 231))
IF (#totalColumnsFound > 0)
BEGIN
DECLARE #tableUpdateQuery VARCHAR(MAX) = 'update ' + #schemaName + '.' + #tableName + ' set ';
DECLARE #columnName VARCHAR(255) -- column name
DECLARE column_cursor CURSOR FOR
SELECT C.name AS ColumnName FROM sys.columns C WHERE OBJECT_ID = #tableID
-- text and nvarchar column data types chosen for me (if you need more like ntext, varcahr see sys.types for their ids)
AND (C.system_type_id = 35 OR c.system_type_id = 231)
OPEN column_cursor
FETCH NEXT FROM column_cursor INTO #columnName
WHILE ##FETCH_STATUS = 0
BEGIN
-- construct the columns for the update query, piece by piece.
-- This is also where you can apply your logic for how to handle the string update.
-- I am trimming string and updating nulls to empty strings here.
SET #tableUpdateQuery = #tableUpdateQuery + ' ' + #columnName + ' = ltrim(rtrim(isnull(' + #columnName + ',''''))),'
FETCH NEXT FROM column_cursor INTO #columnName
END
CLOSE column_cursor
DEALLOCATE column_cursor
-- trim last comma from string
SET #tableUpdateQuery = LEFT(#tableUpdateQuery, LEN(#tableUpdateQuery) - 1)
/** debuging purposes **
print 'Updating table --> ' + #tableName
print #tableUpdateQuery
print ' '
*/
-- execute dynamic sql
EXEC(#tableUpdateQuery)
END
FETCH NEXT FROM table_cursor INTO #tableID, #tableName
END
CLOSE table_cursor
DEALLOCATE table_cursor
END
--GO
this should help you:
/*
Author: sqiller
Description: Searches for a value to replace in all columns from all tables
USE: EXEC dbo.usp_Update_AllTAbles 'work', 'sqiller', 1
#search = Value to look for Replace
#newvalue = the value that will replace #search
#Test = If set to 1, it will only PRINT the UPDATE statement instead of EXEC, useful to see
what is going to update before.
*/
CREATE PROCEDURE dbo.usp_Update_AllTAbles(
#search varchar(100),
#newvalue varchar(100),
#Test bit)
AS
BEGIN
IF NOT EXISTS (select 1 from INFORMATION_SCHEMA.TABLES WHERE TABLE_NAME = 'Tables_to_Update')
BEGIN
CREATE TABLE dbo.Tables_to_Update(
Table_name varchar(100),
Column_name varchar(100),
recordsToUpdate int
)
END
DECLARE #table varchar(100)
DECLARE #column varchar(100)
DECLARE #SQL varchar(max)
SELECT TABLE_SCHEMA+'.'+TABLE_NAME as Table_Name, 0 as Processed INTO #tables from information_schema.tables WHERE TABLE_TYPE != 'VIEW'
WHILE EXISTS (select * from #tables where processed = 0)
BEGIN
SELECT top 1 #table = table_name from #tables where processed = 0
SELECT column_name, 0 as Processed INTO #columns from information_schema.columns where TABLE_SCHEMA+'.'+TABLE_NAME = #table
WHILE EXISTS (SELECT * from #columns where processed = 0)
BEGIN
SELECT top 1 #column = COLUMN_NAME from #columns where processed = 0
SET #SQL = 'INSERT INTO Tables_to_Update
select '''+ #table +''', '''+ #column +''', count(*) from '+#table+ ' where '+ #column +' like ''%'+ #search +'%'''
EXEC(#SQL)
IF EXISTS (SELECT * FROM Tables_to_Update WHERE Table_name = #table)
BEGIN
SET #SQL = 'UPDATE '+ #table + ' SET '+ #column + ' = REPLACE('''+#column+''','''+#search+''','''+ #newvalue +''') WHERE '+ #column + ' like ''%'+#search+'%'''
--UPDATE HERE
IF (#Test = 1)
BEGIN
PRINT #SQL
END
ELSE
BEGIN
EXEC(#SQL)
END
END
UPDATE #columns SET Processed = 1 where COLUMN_NAME = #column
END
DROP TABLE #columns
UPDATE #tables SET Processed = 1 where table_name = #table
END
SELECT * FROM Tables_to_Update where recordsToUpdate > 0
END
The following will find and replace a string in every database (excluding system databases) on every table on the instance you are connected to:
Simply change 'Search String' to whatever you seek and 'Replace String' with whatever you want to replace it with.
--Getting all the databases and making a cursor
DECLARE db_cursor CURSOR FOR
SELECT name
FROM master.dbo.sysdatabases
WHERE name NOT IN ('master','model','msdb','tempdb') -- exclude these databases
DECLARE #databaseName nvarchar(1000)
--opening the cursor to move over the databases in this instance
OPEN db_cursor
FETCH NEXT FROM db_cursor INTO #databaseName
WHILE ##FETCH_STATUS = 0
BEGIN
PRINT #databaseName
--Setting up temp table for the results of our search
DECLARE #Results TABLE(TableName nvarchar(370), RealColumnName nvarchar(370), ColumnName nvarchar(370), ColumnValue nvarchar(3630))
SET NOCOUNT ON
DECLARE #SearchStr nvarchar(100), #ReplaceStr nvarchar(100), #SearchStr2 nvarchar(110)
SET #SearchStr = 'Search String'
SET #ReplaceStr = 'Replace String'
SET #SearchStr2 = QUOTENAME('%' + #SearchStr + '%','''')
DECLARE #TableName nvarchar(256), #ColumnName nvarchar(128)
SET #TableName = ''
--Looping over all the tables in the database
WHILE #TableName IS NOT NULL
BEGIN
DECLARE #SQL nvarchar(2000)
SET #ColumnName = ''
DECLARE #result NVARCHAR(256)
SET #SQL = 'USE ' + #databaseName + '
SELECT #result = MIN(QUOTENAME(TABLE_SCHEMA) + ''.'' + QUOTENAME(TABLE_NAME))
FROM [' + #databaseName + '].INFORMATION_SCHEMA.TABLES
WHERE TABLE_TYPE = ''BASE TABLE'' AND TABLE_CATALOG = ''' + #databaseName + '''
AND QUOTENAME(TABLE_SCHEMA) + ''.'' + QUOTENAME(TABLE_NAME) > ''' + #TableName + '''
AND OBJECTPROPERTY(
OBJECT_ID(
QUOTENAME(TABLE_SCHEMA) + ''.'' + QUOTENAME(TABLE_NAME)
), ''IsMSShipped''
) = 0'
EXEC master..sp_executesql #SQL, N'#result nvarchar(256) out', #result out
SET #TableName = #result
PRINT #TableName
WHILE (#TableName IS NOT NULL) AND (#ColumnName IS NOT NULL)
BEGIN
DECLARE #ColumnResult NVARCHAR(256)
SET #SQL = '
SELECT #ColumnResult = MIN(QUOTENAME(COLUMN_NAME))
FROM [' + #databaseName + '].INFORMATION_SCHEMA.COLUMNS
WHERE TABLE_SCHEMA = PARSENAME(''[' + #databaseName + '].' + #TableName + ''', 2)
AND TABLE_NAME = PARSENAME(''[' + #databaseName + '].' + #TableName + ''', 1)
AND DATA_TYPE IN (''char'', ''varchar'', ''nchar'', ''nvarchar'')
AND TABLE_CATALOG = ''' + #databaseName + '''
AND QUOTENAME(COLUMN_NAME) > ''' + #ColumnName + ''''
PRINT #SQL
EXEC master..sp_executesql #SQL, N'#ColumnResult nvarchar(256) out', #ColumnResult out
SET #ColumnName = #ColumnResult
PRINT #ColumnName
IF #ColumnName IS NOT NULL
BEGIN
INSERT INTO #Results
EXEC
(
'USE ' + #databaseName + '
SELECT ''' + #TableName + ''',''' + #ColumnName + ''',''' + #TableName + '.' + #ColumnName + ''', LEFT(' + #ColumnName + ', 3630)
FROM ' + #TableName + ' (NOLOCK) ' +
' WHERE ' + #ColumnName + ' LIKE ' + #SearchStr2
)
END
END
END
--Declaring another temporary table
DECLARE #time_to_update TABLE(TableName nvarchar(370), RealColumnName nvarchar(370))
INSERT INTO #time_to_update
SELECT TableName, RealColumnName FROM #Results GROUP BY TableName, RealColumnName
DECLARE #MyCursor CURSOR;
BEGIN
DECLARE #t nvarchar(370)
DECLARE #c nvarchar(370)
--Looping over the search results
SET #MyCursor = CURSOR FOR
SELECT TableName, RealColumnName FROM #time_to_update GROUP BY TableName, RealColumnName
--Getting my variables from the first item
OPEN #MyCursor
FETCH NEXT FROM #MyCursor
INTO #t, #c
WHILE ##FETCH_STATUS = 0
BEGIN
-- Updating the old values with the new value
DECLARE #sqlCommand varchar(1000)
SET #sqlCommand = '
USE ' + #databaseName + '
UPDATE [' + #databaseName + '].' + #t + ' SET ' + #c + ' = REPLACE(' + #c + ', ''' + #SearchStr + ''', ''' + #ReplaceStr + ''')
WHERE ' + #c + ' LIKE ''' + #SearchStr2 + ''''
PRINT #sqlCommand
BEGIN TRY
EXEC (#sqlCommand)
END TRY
BEGIN CATCH
PRINT ERROR_MESSAGE()
END CATCH
--Getting next row values
FETCH NEXT FROM #MyCursor
INTO #t, #c
END;
CLOSE #MyCursor ;
DEALLOCATE #MyCursor;
END;
DELETE FROM #time_to_update
DELETE FROM #Results
FETCH NEXT FROM db_cursor INTO #databaseName
END
CLOSE db_cursor
DEALLOCATE db_cursor
Note: this isn't ideal, nor is it optimized
Here is another answer, similar to above (and hopefully more readable/efficient), since I recently had a similar requirement and this is how I solved it.
CREATE OR ALTER PROCEDURE UPDATE_ALL_COLUMNS
#TableNameSearchFilter NVARCHAR(100),
#TableSchema NVARCHAR(100),
#TestValue NVARCHAR(100),
#NewValue NVARCHAR(100)
AS
BEGIN
DECLARE #NRCOLUMNS INT;
DECLARE #i INT = 0;
DECLARE #COLUMN NVARCHAR(100) = '';
DECLARE #SQL NVARCHAR(MAX) = '';
DECLARE #TableToUpdate NVARCHAR(256) = '';
DECLARE #insertingNULL BIT;
IF (#NewValue IS NULL) SET #insertingNULL = 1
ELSE SET #insertingNULL = 0;
WHILE #TableToUpdate IS NOT NULL
BEGIN
SELECT #TableToUpdate = MIN(TABLE_NAME)
FROM INFORMATION_SCHEMA.TABLES
WHERE TABLE_NAME LIKE #TableNameSearchFilter
AND TABLE_SCHEMA = #TableSchema
AND TABLE_NAME > #TableToUpdate;
WITH CTE1 AS
(
SELECT ROW_NUMBER() OVER (ORDER BY ORDINAL_POSITION) AS RN
FROM INFORMATION_SCHEMA.COLUMNS
WHERE TABLE_NAME = #TableToUpdate
AND TABLE_SCHEMA = #TableSchema
AND (#insertingNULL = 0 OR (#insertingNULL = 1 AND IS_NULLABLE = 'YES'))
)
SELECT #i = MIN(RN), #NRCOLUMNS = MAX(RN) FROM CTE1;
WHILE (#i <= #NRCOLUMNS AND #TableToUpdate IS NOT NULL)
BEGIN
WITH CTE AS
(
SELECT *, ROW_NUMBER() OVER (ORDER BY ORDINAL_POSITION) AS RN
FROM INFORMATION_SCHEMA.COLUMNS
WHERE TABLE_NAME = #TableToUpdate
AND TABLE_SCHEMA = #TableSchema
AND (#insertingNULL = 0 OR (#insertingNULL = 1 AND IS_NULLABLE = 'YES'))
)
SELECT #COLUMN = COLUMN_NAME
FROM CTE
WHERE RN = #i;
SET #SQL = #SQL +
N'UPDATE D SET ' + #COLUMN + N' = ' + ISNULL(N'''' + #NewValue + N'''', N'NULL')
+ N' FROM ' + #TableSchema + N'.' + #TableToUpdate + N' D WHERE CAST(D.' + #COLUMN + ' AS NVARCHAR) = ' + ISNULL(N'''' + #TestValue + N'''', N'NULL') + ';'
+ NCHAR(13) + NCHAR(10);
SET #i = #i + 1;
END;
END;
--PRINT SUBSTRING(#SQL, 1, 4000)
--PRINT SUBSTRING(#SQL, 4001, 8000)
--PRINT SUBSTRING(#SQL, 8001, 12000)
--PRINT SUBSTRING(#SQL, 12001, 16000)
--PRINT SUBSTRING(#SQL, 16001, 20000)
--PRINT SUBSTRING(#SQL, 20001, 24000)
EXEC (#SQL)
END
GO
As a usage example:
EXEC UPDATE_ALL_COLUMNS '%temp%', 'dbo', '', NULL
Parameters:
#TableNameSearchFilter - this will be used with the LIKE operator to find all the tables from your database whose names that match this value;
#TableSchema - the schema of the table (usually dbo)
#TestValue - the value to search for in ALL of the columns (and rows) of each found table;
#NewValue - the value to replace #TestValue with. Can also be NULL.
Explanation:
The EXEC statement will find ALL tables whose names contain the word 'temp', on the 'dbo' schema of your database, then search for the value '' (empty string) in ALL columns of ALL of the found tables, then replace this value with a NULL.
Obviously, if you have long(er) column/table names or the update value, make sure to update the limits on the parameters.
Make sure to first comment the last line (EXEC (#SQL)) and uncomment the lines with PRINT, just to get an idea for what the procedure does and how the final statements look like.
This is not going to work (most likely) if you want to search for the NULL value (i.e. to have #TestValue as NULL). Nevertheless, it can be easily changed to accomplish this as well, by replacing the equal sign from the WHERE clause (in the dynamic query) with IS NULL and removing the rest of the line, when #TestValue IS NULL.
Can be easily adapted to search for columns of only certain types (like VARCHAR etc).
The procedure accounts for inserting NULL values, and will only do so in NULLABLE columns.

How do I search database for text string?

Is there any way to search a whole SQL Server database for a text string?
By the whole database I mean tables, views, stored procedures, etc.
If by database you really mean absolutely everything including procedure source code, the easiest will likely be to generate a DB dump and to search for the string within the resulting file. This will be simpler than running all sorts of queries on the information schema.
Here is the code to search certain texts in stored proc
SELECT Distinct SO.Name
FROM sysobjects SO (NOLOCK)
INNER JOIN syscomments SC (NOLOCK) on SO.Id = SC.ID
AND SO.Type = 'P'
AND SC.Text LIKE '%test%'
ORDER BY SO.Name
I got the solution to display / search all tables, columns and SPs with a stored procedure:
CREATE PROC SearchAllTables
(
#SearchStr nvarchar(100)
)
AS
BEGIN
-- Copyright © 2013 Peter Nold. All rights reserved.
-- Purpose: To search all columns of all tables for a given search string
CREATE TABLE #Results (ColumnName nvarchar(370), ColumnValue nvarchar(3630))
SET NOCOUNT ON
DECLARE #TableName nvarchar(256), #ColumnName nvarchar(128), #SearchStr2 nvarchar(110), #myCount varchar(255)
SET #TableName = ''
SET #SearchStr2 = QUOTENAME('%' + #SearchStr + '%','''')
/* debug */
print '************************************************************'
print 'Starting Search For: ' + #SearchStr2
print '************************************************************'
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 QUOTENAME(COLUMN_NAME) > #ColumnName
)
IF #ColumnName IS NOT NULL
BEGIN
-- debug
print 'Searching the field: ' + #TableName + '.' + #ColumnName
INSERT INTO #Results
EXEC
(
'SELECT ''' + #TableName + '.' + #ColumnName + ''', LEFT(CONVERT(varchar(max), ' + #ColumnName + '), 3630)
FROM ' + #TableName + ' (NOLOCK) ' +
' WHERE CONVERT(varchar(max), ' + #ColumnName + ') LIKE ' + #SearchStr2
)
END
END
END
SELECT ColumnName, ColumnValue FROM #Results
SET #myCount = 'Found in #columns: ' + cast((select count(*) from #Results) AS VARCHAR)
print '************************************************************'
print #myCount
print '************************************************************'
END
/* example to search for the text METZ:
***
exec SearchAllTables 'METZ'
*/

Find a value anywhere in a database

Given a number, 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.
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 +
' WHERE ' + #ColumnName + ' LIKE ' + #SearchStr2
)
END
END
END
SELECT ColumnName, ColumnValue FROM #Results
END
To execute the stored procedure :
EXEC SearchAllTables 'YourStringHere'
If you need to run such search only once then you can probably go with any of the scripts already shown in other answers. But otherwise, I’d recommend using ApexSQL Search for this. It’s a free SSMS addin and it really saved me a lot of time.
Before running any of the scripts you should customize it based on the data type you want to search. If you know you are searching for datetime column then there is no need to search through nvarchar columns. This will speed up all of the queries above.
Based on bnkdev's answer I modified Narayana's Code to search all columns even numeric ones.
It'll run slower, but this version actually finds all matches not just those found in text columns.
I can't thank this guy enough. Saved me days of searching by hand!
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 QUOTENAME(COLUMN_NAME) > #ColumnName
)
IF #ColumnName IS NOT NULL
BEGIN
INSERT INTO #Results
EXEC
(
'SELECT ''' + #TableName + '.' + #ColumnName + ''', LEFT(CONVERT(varchar(max), ' + #ColumnName + '), 3630)
FROM ' + #TableName + ' (NOLOCK) ' +
' WHERE CONVERT(varchar(max), ' + #ColumnName + ') LIKE ' + #SearchStr2
)
END
END
END
SELECT ColumnName, ColumnValue FROM #Results
END
This is my independent take on this question that I use for my own work. It works in SQL2000 and greater, allows wildcards, column filtering, and will search most of the normal data types.
A pseudo-code description could be select * from * where any like 'foo'
--------------------------------------------------------------------------------
-- Search all columns in all tables in a database for a string.
-- Does not search: image, sql_variant or user-defined types.
-- Exact search always for money and smallmoney; no wildcards for matching these.
--------------------------------------------------------------------------------
declare #SearchTerm nvarchar(4000) -- Can be max for SQL2005+
declare #ColumnName sysname
--------------------------------------------------------------------------------
-- SET THESE!
--------------------------------------------------------------------------------
set #SearchTerm = N'foo' -- Term to be searched for, wildcards okay
set #ColumnName = N'' -- Use to restrict the search to certain columns, wildcards okay, null or empty string for all cols
--------------------------------------------------------------------------------
-- END SET
--------------------------------------------------------------------------------
set nocount on
declare #TabCols table (
id int not null primary key identity
, table_schema sysname not null
, table_name sysname not null
, column_name sysname not null
, data_type sysname not null
)
insert into #TabCols (table_schema, table_name, column_name, data_type)
select t.TABLE_SCHEMA, c.TABLE_NAME, c.COLUMN_NAME, c.DATA_TYPE
from INFORMATION_SCHEMA.TABLES t
join INFORMATION_SCHEMA.COLUMNS c on t.TABLE_SCHEMA = c.TABLE_SCHEMA
and t.TABLE_NAME = c.TABLE_NAME
where 1 = 1
and t.TABLE_TYPE = 'base table'
and c.DATA_TYPE not in ('image', 'sql_variant')
and c.COLUMN_NAME like case when len(#ColumnName) > 0 then #ColumnName else '%' end
order by c.TABLE_NAME, c.ORDINAL_POSITION
declare
#table_schema sysname
, #table_name sysname
, #column_name sysname
, #data_type sysname
, #exists nvarchar(4000) -- Can be max for SQL2005+
, #sql nvarchar(4000) -- Can be max for SQL2005+
, #where nvarchar(4000) -- Can be max for SQL2005+
, #run nvarchar(4000) -- Can be max for SQL2005+
while exists (select null from #TabCols) begin
select top 1
#table_schema = table_schema
, #table_name = table_name
, #exists = 'select null from [' + table_schema + '].[' + table_name + '] where 1 = 0'
, #sql = 'select ''' + '[' + table_schema + '].[' + table_name + ']' + ''' as TABLE_NAME, * from [' + table_schema + '].[' + table_name + '] where 1 = 0'
, #where = ''
from #TabCols
order by id
while exists (select null from #TabCols where table_schema = #table_schema and table_name = #table_name) begin
select top 1
#column_name = column_name
, #data_type = data_type
from #TabCols
where table_schema = #table_schema
and table_name = #table_name
order by id
-- Special case for money
if #data_type in ('money', 'smallmoney') begin
if isnumeric(#SearchTerm) = 1 begin
set #where = #where + ' or [' + #column_name + '] = cast(''' + #SearchTerm + ''' as ' + #data_type + ')' -- could also cast the column as varchar for wildcards
end
end
-- Special case for xml
else if #data_type = 'xml' begin
set #where = #where + ' or cast([' + #column_name + '] as nvarchar(max)) like ''' + #SearchTerm + ''''
end
-- Special case for date
else if #data_type in ('date', 'datetime', 'datetime2', 'datetimeoffset', 'smalldatetime', 'time') begin
set #where = #where + ' or convert(nvarchar(50), [' + #column_name + '], 121) like ''' + #SearchTerm + ''''
end
-- Search all other types
else begin
set #where = #where + ' or [' + #column_name + '] like ''' + #SearchTerm + ''''
end
delete from #TabCols where table_schema = #table_schema and table_name = #table_name and column_name = #column_name
end
set #run = 'if exists(' + #exists + #where + ') begin ' + #sql + #where + ' print ''' + #table_name + ''' end'
print #run
exec sp_executesql #run
end
set nocount off
I don't put it in proc form since I don't want to maintain it across hundreds of DBs and it's really for ad-hoc work anyway. Please feel free to comment on bug-fixes.
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
I have a solution from a while ago that I kept improving. Also searches within XML columns if told to do so, or searches integer values if providing a integer only string.
/* Reto Egeter, fullparam.wordpress.com */
DECLARE #SearchStrTableName nvarchar(255), #SearchStrColumnName nvarchar(255), #SearchStrColumnValue nvarchar(255), #SearchStrInXML bit, #FullRowResult bit, #FullRowResultRows int
SET #SearchStrColumnValue = '%searchthis%' /* use LIKE syntax */
SET #FullRowResult = 1
SET #FullRowResultRows = 3
SET #SearchStrTableName = NULL /* NULL for all tables, uses LIKE syntax */
SET #SearchStrColumnName = NULL /* NULL for all columns, uses LIKE syntax */
SET #SearchStrInXML = 0 /* Searching XML data may be slow */
IF OBJECT_ID('tempdb..#Results') IS NOT NULL DROP TABLE #Results
CREATE TABLE #Results (TableName nvarchar(128), ColumnName nvarchar(128), ColumnValue nvarchar(max),ColumnType nvarchar(20))
SET NOCOUNT ON
DECLARE #TableName nvarchar(256) = '',#ColumnName nvarchar(128),#ColumnType nvarchar(20), #QuotedSearchStrColumnValue nvarchar(110), #QuotedSearchStrColumnName nvarchar(110)
SET #QuotedSearchStrColumnValue = QUOTENAME(#SearchStrColumnValue,'''')
DECLARE #ColumnNameTable TABLE (COLUMN_NAME nvarchar(128),DATA_TYPE nvarchar(20))
WHILE #TableName IS NOT NULL
BEGIN
SET #TableName =
(
SELECT MIN(QUOTENAME(TABLE_SCHEMA) + '.' + QUOTENAME(TABLE_NAME))
FROM INFORMATION_SCHEMA.TABLES
WHERE TABLE_TYPE = 'BASE TABLE'
AND TABLE_NAME LIKE COALESCE(#SearchStrTableName,TABLE_NAME)
AND QUOTENAME(TABLE_SCHEMA) + '.' + QUOTENAME(TABLE_NAME) > #TableName
AND OBJECTPROPERTY(OBJECT_ID(QUOTENAME(TABLE_SCHEMA) + '.' + QUOTENAME(TABLE_NAME)), 'IsMSShipped') = 0
)
IF #TableName IS NOT NULL
BEGIN
DECLARE #sql VARCHAR(MAX)
SET #sql = 'SELECT 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 (' + CASE WHEN ISNUMERIC(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(#SearchStrColumnValue,'%',''),'_',''),'[',''),']',''),'-','')) = 1 THEN '''tinyint'',''int'',''smallint'',''bigint'',''numeric'',''decimal'',''smallmoney'',''money'',' ELSE '' END + '''char'',''varchar'',''nchar'',''nvarchar'',''timestamp'',''uniqueidentifier''' + CASE #SearchStrInXML WHEN 1 THEN ',''xml''' ELSE '' END + ')
AND COLUMN_NAME LIKE COALESCE(' + CASE WHEN #SearchStrColumnName IS NULL THEN 'NULL' ELSE '''' + #SearchStrColumnName + '''' END + ',COLUMN_NAME)'
INSERT INTO #ColumnNameTable
EXEC (#sql)
WHILE EXISTS (SELECT TOP 1 COLUMN_NAME FROM #ColumnNameTable)
BEGIN
PRINT #ColumnName
SELECT TOP 1 #ColumnName = COLUMN_NAME,#ColumnType = DATA_TYPE FROM #ColumnNameTable
SET #sql = 'SELECT ''' + #TableName + ''',''' + #ColumnName + ''',' + CASE #ColumnType WHEN 'xml' THEN 'LEFT(CAST(' + #ColumnName + ' AS nvarchar(MAX)), 4096),'''
WHEN 'timestamp' THEN 'master.dbo.fn_varbintohexstr('+ #ColumnName + '),'''
ELSE 'LEFT(' + #ColumnName + ', 4096),''' END + #ColumnType + '''
FROM ' + #TableName + ' (NOLOCK) ' +
' WHERE ' + CASE #ColumnType WHEN 'xml' THEN 'CAST(' + #ColumnName + ' AS nvarchar(MAX))'
WHEN 'timestamp' THEN 'master.dbo.fn_varbintohexstr('+ #ColumnName + ')'
ELSE #ColumnName END + ' LIKE ' + #QuotedSearchStrColumnValue
INSERT INTO #Results
EXEC(#sql)
IF ##ROWCOUNT > 0 IF #FullRowResult = 1
BEGIN
SET #sql = 'SELECT TOP ' + CAST(#FullRowResultRows AS VARCHAR(3)) + ' ''' + #TableName + ''' AS [TableFound],''' + #ColumnName + ''' AS [ColumnFound],''FullRow>'' AS [FullRow>],*' +
' FROM ' + #TableName + ' (NOLOCK) ' +
' WHERE ' + CASE #ColumnType WHEN 'xml' THEN 'CAST(' + #ColumnName + ' AS nvarchar(MAX))'
WHEN 'timestamp' THEN 'master.dbo.fn_varbintohexstr('+ #ColumnName + ')'
ELSE #ColumnName END + ' LIKE ' + #QuotedSearchStrColumnValue
EXEC(#sql)
END
DELETE FROM #ColumnNameTable WHERE COLUMN_NAME = #ColumnName
END
END
END
SET NOCOUNT OFF
SELECT TableName, ColumnName, ColumnValue, ColumnType, COUNT(*) AS Count FROM #Results
GROUP BY TableName, ColumnName, ColumnValue, ColumnType
Source:
http://fullparam.wordpress.com/2012/09/07/fck-it-i-am-going-to-search-all-tables-all-collumns/
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
Thanks for the really useful script.
You may need to add the following modification to the code if your tables have non-convertable fields:
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 NOT IN ('text', 'image', 'ntext')
AND QUOTENAME(COLUMN_NAME) > #ColumnName
)
Chris
Here, very sweet and small solution:
1) create a store procedure:
create procedure get_table
#find_str varchar(50)
as
begin
declare #col_name varchar(500), #tab_name varchar(500);
declare #find_tab TABLE(table_name varchar(100), column_name varchar(100));
DECLARE tab_col cursor for
select C.name as 'col_name', T.name as tab_name
from sys.tables as T
left outer join sys.columns as C on C.object_id=T.object_id
left outer join sys.types as TP on C.system_type_id=TP.system_type_id
where type='U'
and TP.name in('text','ntext','varchar','char','nvarchar','nchar');
open tab_col
fetch next from tab_col into #col_name, #tab_name
while ##FETCH_STATUS = 0
begin
insert into #find_tab
exec('select ''' + #tab_name + ''',''' + #col_name + ''' from ' + #tab_name +
' where ' + #col_name + '=''' + #find_str + ''' group by ' +
#col_name + ' having count(*)>0');
fetch next from tab_col into #col_name, #tab_name;
end
CLOSE tab_col;
DEALLOCATE tab_col;
select table_name, column_name from #find_tab;
end
==========================
2) call procedure by calling store procedure:
exec get_table 'serach_string';
If you have phpMyAdmin installed use its Search feature.
Select your DataBase.
Be sure you do have selected DataBase, not a table, otherwise you'll get a completely different search dialog.
Click Search tab
List item Choose the search term you want
Choose the tables to search
Another way using JOIN and CURSOR:
USE My_Database;
-- Store results in a local temp table so that. I'm using a
-- local temp table so that I can access it in SP_EXECUTESQL.
create table #tmp (
tbl nvarchar(max),
col nvarchar(max),
val nvarchar(max)
);
declare #tbl nvarchar(max);
declare #col nvarchar(max);
declare #q nvarchar(max);
declare #search nvarchar(max) = 'my search key';
-- Create a cursor on all columns in the database
declare c cursor for
SELECT tbls.TABLE_NAME, cols.COLUMN_NAME FROM INFORMATION_SCHEMA.TABLES AS tbls
JOIN INFORMATION_SCHEMA.COLUMNS AS cols
ON tbls.TABLE_NAME = cols.TABLE_NAME
-- For each table and column pair, see if the search value exists.
open c
fetch next from c into #tbl, #col
while ##FETCH_STATUS = 0
begin
-- Look for the search key in current table column and if found add it to the results.
SET #q = 'INSERT INTO #tmp SELECT ''' + #tbl + ''', ''' + #col + ''', ' + #col + ' FROM ' + #tbl + ' WHERE ' + #col + ' LIKE ''%' + #search + '%'''
EXEC SP_EXECUTESQL #q
fetch next from c into #tbl, #col
end
close c
deallocate c
-- Get results
select * from #tmp
-- Remove local temp table.
drop table #tmp
You might need to build an inverted index for your database. It is assured to be pretty fast.
-- exec pSearchAllTables 'M54*'
ALTER PROC pSearchAllTables (#SearchStr NVARCHAR(100))
AS
BEGIN
-- A procedure to search all tables in a database for a value
-- Note: Use * or % for wildcard
DECLARE
#Results TABLE([Schema.Table.ColumnName] NVARCHAR(370), ColumnValue NVARCHAR(3630))
SET NOCOUNT ON
DECLARE
#TableName NVARCHAR(256) = ''
, #ColumnName NVARCHAR(128)
, #SearchStr2 NVARCHAR(110) = QUOTENAME(REPLACE(#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
[Schema.Table.ColumnName]
, ColumnValue
FROM #Results
GROUP BY
[Schema.Table.ColumnName]
, ColumnValue
END
For Development purpose you can just export the required tables data into a single HTML and make a direct search on it.
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;
I was looking for a just a numeric value = 6.84 - using the other answers here I was able to limit my search to this
Declare #sourceTable Table(id INT NOT NULL IDENTITY PRIMARY KEY, table_name varchar(1000), column_name varchar(1000))
Declare #resultsTable Table(id INT NOT NULL IDENTITY PRIMARY KEY, table_name varchar(1000))
Insert into #sourceTable(table_name, column_name)
select schema_name(t.schema_id) + '.' + t.name as[table], c.name as column_name
from sys.columns c
join sys.tables t
on t.object_id = c.object_id
where type_name(user_type_id) in ('decimal', 'numeric', 'smallmoney', 'money', 'float', 'real')
order by[table], c.column_id;
DECLARE db_cursor CURSOR FOR
Select table_name, column_name from #sourceTable
DECLARE #mytablename VARCHAR(1000);
DECLARE #mycolumnname VARCHAR(1000);
OPEN db_cursor;
FETCH NEXT FROM db_cursor INTO #mytablename, #mycolumnname
WHILE # #FETCH_STATUS = 0
BEGIN
Insert into #ResultsTable(table_name)
EXEC('SELECT ''' + #mytablename + '.' + #mycolumnname + ''' FROM ' + #mytablename + ' (NOLOCK) ' +
' WHERE ' + #mycolumnname + '=6.84')
FETCH NEXT FROM db_cursor INTO #mytablename, #mycolumnname
END;
CLOSE db_cursor;
DEALLOCATE db_cursor;
Select Distinct(table_name) from #ResultsTable
There are lots of workable answers already. I just wanted to share one I wrote that has additional functionality.
--=======================================================================
-- MSSQL Unified Search
-- Minimum compatibility level = 130 (SQL Server 2016)
-- NOTE: The minimum compatibility level is required by the built-in STRING_SPLIT() function.
-- However, you can create the STRING_SPLIT() function at the bottom of this script for
-- lower versions of MSSQL Server.
--
-- Usage:
-- Set the parameters below and execute this script.
--
/************************ Enter Parameters Here ************************/
/**/
/**/ DECLARE #SearchString VARCHAR(1000) = 'string to search for'; -- Accepts SQL wilcards
/**/
/**/ DECLARE #IncludeUserTables BIT = 1;
/**/ DECLARE #IncludeViews BIT = 0;
/**/ DECLARE #IncludeStoredProcedures BIT = 0;
/**/ DECLARE #IncludeFunctions BIT = 0;
/**/ DECLARE #IncludeTriggers BIT = 0;
/**/
/**/ DECLARE #DebugMode BIT = 0;
/**/ DECLARE #ExcludeColumnTypes NVARCHAR(500) = 'text, ntext, char, nchar, timestamp, bigint, tinyint, smallint, bit, date, time, smalldatetime, datetime, datetime2, real, money, float, decimal, binary, varbinary, image'; -- Comma delimited list
/**/
/***********************************************************************/
SET NOCOUNT ON;
SET #SearchString = QUOTENAME(#SearchString,'''');
DECLARE #Results TABLE ([ObjectType] NVARCHAR(200), [ObjectName] NVARCHAR(200), [ColumnName] NVARCHAR(400), [Value] NVARCHAR(MAX), [SelectStatement] NVARCHAR(1000));
DECLARE #ExcludeColTypes TABLE (system_type_id INT);
INSERT INTO #ExcludeColTypes ([system_type_id])
SELECT [system_type_id]
FROM sys.types WHERE
[name] IN (
SELECT LTRIM(RTRIM([value])) FROM STRING_SPLIT(#ExcludeColumnTypes,',')
);
DECLARE #ObjectType NVARCHAR(200);
DECLARE #ObjectName NVARCHAR(200);
DECLARE #Value NVARCHAR(MAX);
DECLARE #SelectStatement NVARCHAR(1000);
DECLARE #Query NVARCHAR(4000);
/********************* Table Objects *********************/
IF (#IncludeUserTables = 1)
BEGIN
DECLARE #TableObjectId INT = (SELECT MIN([object_id]) FROM sys.tables);
DECLARE #ColumnId INT;
WHILE #TableObjectId IS NOT NULL
BEGIN
SELECT #ObjectType = 'USER TABLE';
SELECT #ObjectName = '[' + SCHEMA_NAME([schema_id]) + '].[' + OBJECT_NAME(#TableObjectId) + ']' FROM sys.tables WHERE [object_id] = #TableObjectId;
SET #ColumnId = (SELECT MIN([column_id]) FROM sys.columns WHERE [system_type_id] NOT IN (SELECT [system_type_id] FROM #ExcludeColTypes) AND [object_id] = #TableObjectId);
WHILE #ColumnId IS NOT NULL
BEGIN
SELECT #Value = '[' + [name] +']' FROM sys.columns WHERE [object_id] = #TableObjectId AND column_id = #ColumnId;
SET #SelectStatement = 'SELECT * FROM ' + #ObjectName + ' WHERE CAST(' + #Value + ' AS NVARCHAR(4000)) LIKE ' + #SearchString + ';';
SET #Query = 'SELECT '
+ QUOTENAME(#ObjectType, '''')
+ ', ' + QUOTENAME(#ObjectName, '''')
+ ', ' + QUOTENAME(#Value, '''')
+ ', ' + #Value
+ ', ''' + REPLACE(#SelectStatement,'''','''''') + ''''
+ ' FROM ' + #ObjectName
+ ' WHERE CAST(' + #Value + ' AS NVARCHAR(4000)) LIKE ' + #SearchString + ';';
IF #DebugMode = 0
BEGIN
INSERT INTO #Results EXEC(#Query);
END;
ELSE
BEGIN
PRINT 'Select Statement: ' + #SelectStatement;
PRINT 'Query: ' + #Query;
END;
SET #ColumnId = (SELECT MIN([column_id]) FROM sys.columns WHERE [system_type_id] NOT IN (SELECT [system_type_id] FROM #ExcludeColTypes) AND [object_id] = #TableObjectId AND [column_id] > #ColumnId);
END;
SET #TableObjectId = (SELECT MIN([object_id]) FROM sys.tables WHERE [object_id] > #TableObjectId);
END;
END;
/********************* Objects Other than Tables *********************/
SET #Query = 'SELECT ' +
'ObjectType = CASE ' +
'WHEN b.[type] = ''V'' THEN ''VIEW'' ' +
'WHEN b.[type] = ''P'' THEN ''STORED PROCEDURE'' ' +
'WHEN b.[type] = ''FN'' THEN ''SCALAR-VALUED FUNCTION'' ' +
'WHEN b.[type] = ''IF'' THEN ''TABLE-VALUED FUNCTION'' ' +
'WHEN b.[type] = ''TR'' THEN ''TRIGGER'' ' +
'END ' +
',[ObjectName] = ''['' + SCHEMA_NAME(b.[schema_id]) + ''].['' + OBJECT_NAME(a.[object_id]) + '']'' ' +
',[ColumnName] = NULL ' +
',[Value] = a.[definition] ' +
',[SelectStatement] = ''SP_HELPTEXT '' + QUOTENAME(''['' + SCHEMA_NAME(b.[schema_id]) + ''].['' + OBJECT_NAME(a.[object_id]) + '']'','''''''') + '';'' ' +
'FROM [sys].[sql_modules] a ' +
'JOIN [sys].[objects] b ON a.[object_id] = b.[object_id] ' +
'WHERE ' +
'( ' +
' a.[definition] LIKE ' + #SearchString +
') ' +
'AND ' +
'( ' +
' ( ' +
CAST(#IncludeViews AS VARCHAR(1)) + ' = 1 ' +
' AND ' +
' b.[type] IN (''V'') ' +
' ) ' +
' OR ' +
' ( ' +
CAST(#IncludeStoredProcedures AS VARCHAR(1)) + ' = 1 ' +
' AND ' +
' b.[type] IN (''P'') ' +
' ) ' +
' OR ' +
' ( ' +
CAST(#IncludeFunctions AS VARCHAR(1)) + ' = 1 ' +
' AND ' +
' b.[type] IN (''FN'',''IF'') ' +
' ) ' +
' OR ' +
' ( ' +
CAST(#IncludeTriggers AS VARCHAR(1)) + ' = 1 ' +
' AND ' +
' b.[type] IN (''TR'') ' +
' ) ' +
'); ';
IF #DebugMode = 0
BEGIN
INSERT INTO #Results EXEC(#Query);
END;
ELSE
BEGIN
PRINT 'Select Statement: ' + #SelectStatement;
PRINT 'Query: ' + #Query;
END;
IF #DebugMode = 0
BEGIN
SELECT
[ObjectType]
,[ObjectName]
,[ColumnName]
,[Value]
,[Count] = CASE
WHEN [ObjectType] IN ('USER TABLE') THEN COUNT(1)
ELSE NULL
END
,[SelectStatement]
FROM #Results
GROUP BY [ObjectType], [ObjectName], [ColumnName], [Value], [SelectStatement]
ORDER BY [Value];
END;
/********************** STRING_SPLIT() FUNCTION **********************
CREATE FUNCTION STRING_SPLIT (
#Expression nvarchar(4000)
,#Delimiter nvarchar(100)
)
RETURNS #Ret TABLE ([value] NVARCHAR(4000))
AS
BEGIN
DECLARE #Start INT = 0, #End INT, #Length INT;
SELECT #End = CHARINDEX(#Delimiter,#Expression), #Length = #End - #Start;
IF #End <= 0
BEGIN
INSERT INTO #Ret ([value]) VALUES (#Expression);
END
ELSE
BEGIN
WHILE #Length >= 0
BEGIN
INSERT INTO #Ret ([value])
SELECT ltrim(rtrim(substring(#Expression,#Start,#Length)));
SELECT #Start = #End + LEN(#Delimiter)
SELECT #End = CHARINDEX(#Delimiter,#Expression,#Start)
IF #End < 1
SELECT #End = LEN(#Expression) + 1;
SELECT #Length = #End - #Start;
END;
END;
RETURN;
END;
*********************************************************************/
By far the best and most universal solution I found is to pipe a dump of the db through to a grep of what you are searching for.
e.g. for Mysql:
mysqldump -pPASSWORD database | grep 'search phrase'
Or if you get too many results, you can then output them to a file:
mysqldump -pPASSWORD database | grep 'search phrase' > results.txt

Resources