Tsql. Dynamic SQL in cursor - sql

‌‌‌Please I REALLY NEED YOUR HELP !!
I‌ want to create a dynamic sql in a cursor.
I‌ want to replace the database DB1 by the variable #Database
I have lot error. I don't know why !!!
‌‌`
‌declare #SQL NVARCHAR (max)
DECLARE #database NVARCHAR (50) = 'TEST'
--DECLARE c CURSOR FOR
IF OBJECT_ID('tempdb..#SQL') IS NOT NULL
DROP TABLE #SQL
SELECT SQL = 'IF OBJECT_ID('''
+ QUOTENAME(SCHEMA_NAME(o.[schema_id]))
+ '.' + QUOTENAME(o.name) + ''') IS NOT NULL
BEGIN
DROP VIEW '
+ QUOTENAME(SCHEMA_NAME(o.[schema_id]))
+ '.' + QUOTENAME(o.name) + ';
END'
+ CHAR(13) + CHAR(10) + 'GO'
+ CHAR(13) + CHAR(10) + Definition
into #SQL
FROM [DB1].sys.sql_modules AS s
INNER JOIN [DB1].sys.objects AS o
ON s.[object_id] = o.[object_id]
WHERE o.type_desc = 'VIEW';
DECLARE c CURSOR FOR
SELECT SQL FROM #SQL
OPEN c
FETCH NEXT FROM c INTO #sql
WHILE ##FETCH_STATUS = 0
BEGIN
-- SET #sql = REPLACE(#sql,'''','''''')
SET #sql = ' EXEC (''' + REPLACE(REPLACE(#SQL, '''', ''''''), 'GO', '''); EXEC(''') + ''');'
--'USE [' + #Name + ']; EXEC(''' + #sql + ''')'
exec (#sql)
FETCH NEXT FROM c INTO #sql
END
CLOSE c
DEALLOCATE c
`

Try to remove the square bracket in 2 lines. Hope to help, my friend.
FROM DB1.sys.sql_modules AS s
INNER JOIN DB1.sys.objects AS o

Good day,
Please check if below code solve your needs:
Note! (1) THIS CODE WAS NOT TESTED! (2) Read the comments inside the code!
-- Step 1: INSERT into New Table
IF OBJECT_ID('tempdb..#SQL') IS NOT NULL
DROP TABLE #SQL
SELECT MySQL = '
IF OBJECT_ID(''' + QUOTENAME(SCHEMA_NAME(o.[schema_id])) + '.' + QUOTENAME(o.name) + ''') IS NOT NULL BEGIN
DROP VIEW ' + QUOTENAME(SCHEMA_NAME(o.[schema_id])) + '.' + QUOTENAME(o.name) + ';
END
GO
' + [definition]
into #SQL
FROM sys.sql_modules AS s
INNER JOIN sys.objects AS o ON s.[object_id] = o.[object_id]
WHERE o.type_desc = 'VIEW';
-- always test each step! If this step seems OK, then we will mark the select as comment
select * from #SQL
-- Step 2: loop through all rows that we inserted to the new table, using CURSOR
DECLARE c CURSOR FOR
SELECT MySQL FROM #SQL
OPEN c
declare #SQL NVARCHAR (max)
FETCH NEXT FROM c INTO #sql
WHILE ##FETCH_STATUS = 0 BEGIN
SET #sql =
+ '------START-----' -- This will help us during the check while we pring the text
+ CHAR(13) + CHAR(10)
+ 'EXEC (''' + REPLACE(REPLACE(#SQL, '''', ''''''), 'GO', '''); EXEC(''') + ''');'
-- Again, always check result BEFORE executing it!
PRINT #sql
-- If above results are all well and only if you tested them manually, the we can make the PRINT a comment and exeute the query
--exec (#sql)
FETCH NEXT FROM c INTO #sql
END
CLOSE c
DEALLOCATE c

Related

iterate over all databases, insert data into temp table and display data [duplicate]

I have a stored procedure which scans all tables in my DB for a certain column (codevalues).
It then prints the distinct values for that column and its table it belongs in.
Each column can belong to many tables.
i.e. codeX can be found in Table A and Table B.
ActualCode in TableA
ActualCode
----------
0
1
2
(3 row(s) affected)
--------------------
ActualCode in TableB
ActualCode
----------
0
(1 row(s) affected)
I am trying to figure out how to scan each row in my results, and then insert that row into a new table in a new database.
For example, i want to grab 0 from below for TableA, and insert a row into a new table and store the Value(0) and the Table name (TableA)
And then do the same for value 1...2 etc, and then repeat the same for the next table.
My query is as this:
DECLARE cursorColumnNames CURSOR FOR SELECT DISTINCT COLUMN_NAME, TABLE_NAME FROM
INFORMATION_SCHEMA.COLUMNS
WHERE COLUMN_NAME LIKE '%ActualCode%' AND TABLE_CATALOG = 'db1' AND COLUMN_NAME NOT
IN(select ColumnName from [DataDictionary].[dbo].[Code])
OPEN cursorColumnNames
FETCH NEXT FROM cursorColumnNames INTO #columnName, #tableName;
WHILE ##FETCH_STATUS = 0
BEGIN
PRINT #columnName + ' in ' + #tableName;
PRINT ' '
SET #SqlQuery = 'SELECT DISTINCT ' + #columnName + ' FROM ' + #tableName;
EXEC (#SqlQuery);
PRINT '--------------------'
FETCH NEXT FROM cursorColumnNames INTO #columnName, #tableName;
END;
CLOSE cursorColumnNames;
DEALLOCATE cursorColumnNames;
I tried grabbing each top 1 value and then add that and repeat until all data has been transferred.
But my query looks for columns that are not in the second db so after the first iteration, my query returns 0 records.
So i am confused as what to do or try.
I do not want to create a new table, the table already exists.
The table i want to add the individual rows to is defined as this:
CodeInsertID TableName ColumnName CodeNo
4648 TableA ActualCode 0
4647 TableA ActualCode 1
4646 TableA ActualCode 2
4645 TableB ActualCode 0
can u try like this ? its work for me.
Declare #SqlQuery nvarchar(max),
#columnName nvarchar(50),
#tableName nvarchar(50)
Declare #table table (TableName nvarchar(50) , ColumnName nvarchar(50) , CodeNo int)
DECLARE cursorColumnNames CURSOR FOR SELECT DISTINCT COLUMN_NAME, TABLE_NAME FROM
INFORMATION_SCHEMA.COLUMNS
WHERE COLUMN_NAME LIKE '%ActualCode%' AND TABLE_CATALOG = 'db1' AND COLUMN_NAME NOT
IN(select ColumnName from [DataDictionary].[dbo].[Code])
OPEN cursorColumnNames
FETCH NEXT FROM cursorColumnNames INTO #columnName, #tableName;
WHILE ##FETCH_STATUS = 0
BEGIN
--PRINT #columnName + ' in ' + #tableName;
--PRINT ' '
SET #SqlQuery = 'SELECT DISTINCT ''' + #tablename+ ''', '''+ #columnName+ ''' , ' + #columnName + ' FROM [' + #tableName + ']';
PRINT #SqlQuery
INSERT INTO #table (TableName,ColumnName,CodeNo)
EXEC (#SqlQuery);
--PRINT '--------------------'
FETCH NEXT FROM cursorColumnNames INTO #columnName, #tableName;
END;
CLOSE cursorColumnNames;
DEALLOCATE cursorColumnNames;
SELECT * from #table
Cursors are really slow, you can do this in one single dynamic statement, which we can build in one shot.
You also need to quote the column and table names with QUOTENAME otherwise your code may not work.
Note: To escape a single quote ' in a string, use ''. Don't get confused about which code is part of the dynamic section and which part is static.
DECLARE #sql nvarchar(max) =
N'INSERT INTO myTABLE (TableName, ColumnName, CodeNo)
' +
(SELECT STRING_AGG(
N'SELECT
N' + QUOTENAME(t.name, '''') + N',
N' + QUOTENAME(c.name, '''') + N',
CAST(' + QUOTENAME(c.name) + N' AS nvarchar(max)) -- or whatever your column type is here
FROM db1.' + QUOTENAME(s.name) + N'.' + QUOTENAME(t.name),
CAST(N'
UNION ALL
' AS nvarchar(max))
FROM db1.sys.tables t
JOIN db1.sys.schemas s ON s.schema_id = t.schema_id
JOIN db1.sys.columns c ON c.object_id = t.object_id
WHERE c.name LIKE N'%ActualCode%'
AND c.name NOT IN (SELECT ColumnName FROM [DataDictionary].[dbo].[Code])
);
-- PRINT #sql; -- for testing
EXEC sp_executesql #sql;
You say you only have SQL Server 2014, so you would have to use either a cursor or FOR XML PATH. You can still build the query, then execute it in one shot:
DECLARE #sql nvarchar(max) =
N'INSERT INTO myTABLE (TableName, ColumnName, CodeNo)
';
DECLARE #cur CURSOR;
SET #cur = CURSOR FAST_FORWARD FOR
SELECT
N'SELECT
N' + QUOTENAME(t.name, '''') + N',
N' + QUOTENAME(c.name, '''') + N',
CAST(' + QUOTENAME(c.name) + N' AS nvarchar(max)) -- or whatever your column type is here
FROM db1.' + QUOTENAME(s.name) + N'.' + QUOTENAME(t.name)
FROM db1.sys.tables t
JOIN db1.sys.schemas s ON s.schema_id = t.schema_id
JOIN db1.sys.columns c ON c.object_id = t.object_id
WHERE c.name LIKE N'%ActualCode%'
AND c.name NOT IN (SELECT ColumnName FROM [DataDictionary].[dbo].[Code])
;
OPEN #cur;
DECLARE #tableSql nvarchar(max);
FETCH NEXT FROM #cur INTO #tableSql;
SET #sql = #sql + #tableSql;
WHILE (##FETCH_STATUS = 0)
BEGIN
FETCH NEXT FROM #cur INTO #tableSql;
SET #sql = #sql + N'
UNION ALL
' + #tableSql;
END;
-- PRINT #sql; -- for testing
EXEC sp_executesql #sql;
There is no need to close or deallocate as it's a local variable and will be closed automatically at the end of the batch

How to store copy each row from one table into another table

I have a stored procedure which scans all tables in my DB for a certain column (codevalues).
It then prints the distinct values for that column and its table it belongs in.
Each column can belong to many tables.
i.e. codeX can be found in Table A and Table B.
ActualCode in TableA
ActualCode
----------
0
1
2
(3 row(s) affected)
--------------------
ActualCode in TableB
ActualCode
----------
0
(1 row(s) affected)
I am trying to figure out how to scan each row in my results, and then insert that row into a new table in a new database.
For example, i want to grab 0 from below for TableA, and insert a row into a new table and store the Value(0) and the Table name (TableA)
And then do the same for value 1...2 etc, and then repeat the same for the next table.
My query is as this:
DECLARE cursorColumnNames CURSOR FOR SELECT DISTINCT COLUMN_NAME, TABLE_NAME FROM
INFORMATION_SCHEMA.COLUMNS
WHERE COLUMN_NAME LIKE '%ActualCode%' AND TABLE_CATALOG = 'db1' AND COLUMN_NAME NOT
IN(select ColumnName from [DataDictionary].[dbo].[Code])
OPEN cursorColumnNames
FETCH NEXT FROM cursorColumnNames INTO #columnName, #tableName;
WHILE ##FETCH_STATUS = 0
BEGIN
PRINT #columnName + ' in ' + #tableName;
PRINT ' '
SET #SqlQuery = 'SELECT DISTINCT ' + #columnName + ' FROM ' + #tableName;
EXEC (#SqlQuery);
PRINT '--------------------'
FETCH NEXT FROM cursorColumnNames INTO #columnName, #tableName;
END;
CLOSE cursorColumnNames;
DEALLOCATE cursorColumnNames;
I tried grabbing each top 1 value and then add that and repeat until all data has been transferred.
But my query looks for columns that are not in the second db so after the first iteration, my query returns 0 records.
So i am confused as what to do or try.
I do not want to create a new table, the table already exists.
The table i want to add the individual rows to is defined as this:
CodeInsertID TableName ColumnName CodeNo
4648 TableA ActualCode 0
4647 TableA ActualCode 1
4646 TableA ActualCode 2
4645 TableB ActualCode 0
can u try like this ? its work for me.
Declare #SqlQuery nvarchar(max),
#columnName nvarchar(50),
#tableName nvarchar(50)
Declare #table table (TableName nvarchar(50) , ColumnName nvarchar(50) , CodeNo int)
DECLARE cursorColumnNames CURSOR FOR SELECT DISTINCT COLUMN_NAME, TABLE_NAME FROM
INFORMATION_SCHEMA.COLUMNS
WHERE COLUMN_NAME LIKE '%ActualCode%' AND TABLE_CATALOG = 'db1' AND COLUMN_NAME NOT
IN(select ColumnName from [DataDictionary].[dbo].[Code])
OPEN cursorColumnNames
FETCH NEXT FROM cursorColumnNames INTO #columnName, #tableName;
WHILE ##FETCH_STATUS = 0
BEGIN
--PRINT #columnName + ' in ' + #tableName;
--PRINT ' '
SET #SqlQuery = 'SELECT DISTINCT ''' + #tablename+ ''', '''+ #columnName+ ''' , ' + #columnName + ' FROM [' + #tableName + ']';
PRINT #SqlQuery
INSERT INTO #table (TableName,ColumnName,CodeNo)
EXEC (#SqlQuery);
--PRINT '--------------------'
FETCH NEXT FROM cursorColumnNames INTO #columnName, #tableName;
END;
CLOSE cursorColumnNames;
DEALLOCATE cursorColumnNames;
SELECT * from #table
Cursors are really slow, you can do this in one single dynamic statement, which we can build in one shot.
You also need to quote the column and table names with QUOTENAME otherwise your code may not work.
Note: To escape a single quote ' in a string, use ''. Don't get confused about which code is part of the dynamic section and which part is static.
DECLARE #sql nvarchar(max) =
N'INSERT INTO myTABLE (TableName, ColumnName, CodeNo)
' +
(SELECT STRING_AGG(
N'SELECT
N' + QUOTENAME(t.name, '''') + N',
N' + QUOTENAME(c.name, '''') + N',
CAST(' + QUOTENAME(c.name) + N' AS nvarchar(max)) -- or whatever your column type is here
FROM db1.' + QUOTENAME(s.name) + N'.' + QUOTENAME(t.name),
CAST(N'
UNION ALL
' AS nvarchar(max))
FROM db1.sys.tables t
JOIN db1.sys.schemas s ON s.schema_id = t.schema_id
JOIN db1.sys.columns c ON c.object_id = t.object_id
WHERE c.name LIKE N'%ActualCode%'
AND c.name NOT IN (SELECT ColumnName FROM [DataDictionary].[dbo].[Code])
);
-- PRINT #sql; -- for testing
EXEC sp_executesql #sql;
You say you only have SQL Server 2014, so you would have to use either a cursor or FOR XML PATH. You can still build the query, then execute it in one shot:
DECLARE #sql nvarchar(max) =
N'INSERT INTO myTABLE (TableName, ColumnName, CodeNo)
';
DECLARE #cur CURSOR;
SET #cur = CURSOR FAST_FORWARD FOR
SELECT
N'SELECT
N' + QUOTENAME(t.name, '''') + N',
N' + QUOTENAME(c.name, '''') + N',
CAST(' + QUOTENAME(c.name) + N' AS nvarchar(max)) -- or whatever your column type is here
FROM db1.' + QUOTENAME(s.name) + N'.' + QUOTENAME(t.name)
FROM db1.sys.tables t
JOIN db1.sys.schemas s ON s.schema_id = t.schema_id
JOIN db1.sys.columns c ON c.object_id = t.object_id
WHERE c.name LIKE N'%ActualCode%'
AND c.name NOT IN (SELECT ColumnName FROM [DataDictionary].[dbo].[Code])
;
OPEN #cur;
DECLARE #tableSql nvarchar(max);
FETCH NEXT FROM #cur INTO #tableSql;
SET #sql = #sql + #tableSql;
WHILE (##FETCH_STATUS = 0)
BEGIN
FETCH NEXT FROM #cur INTO #tableSql;
SET #sql = #sql + N'
UNION ALL
' + #tableSql;
END;
-- PRINT #sql; -- for testing
EXEC sp_executesql #sql;
There is no need to close or deallocate as it's a local variable and will be closed automatically at the end of the batch

List tables with recently modified records

I have a field namely Modified_Dt of type Datetime in all of my tables, to keep track of last modified date and time for a record.
Now, let's say I need to know which tables has records that has been modified recently(like today).
How do I write a query for that? How do I query multiple tables?
By the way, I am using MS SQL Server 2008 R2.
USE MASTER
GO
DECLARE #ObjectName NVARCHAR(255)
DECLARE TablesList CURSOR
FOR select object_name(object_id, db_id('DBStackExchange'))
from [DBStackExchange].sys.columns
where name = 'Modified_Dt'
OPEN TablesList
FETCH NEXT FROM TablesList INTO #ObjectName
WHILE ##FETCH_STATUS = 0
BEGIN
exec
( 'If exists ( SELECT 1 FROM DBStackExchange.dbo.[' + #ObjectName
+ ']
Where convert(varchar(20),Modified_Dt,103)>=convert(varchar(20),getdate(),103))
Print ''' + #ObjectName + '''
'
)
FETCH NEXT FROM TablesList INTO #ObjectName
END
CLOSE TablesList
DEALLOCATE TablesList
Note: Replace 'DBStackExchange' with your Database name
declare #T table (T_Name nvarchar(255), M datetime)
declare #T_Name nvarchar(255), #SQLT nvarchar(max)
declare c cursor for select name from sys.tables
open c
fetch next from c into #T_Name
while ##fetch_status = 0 begin
set #SQLT = 'select top 1 ''' + #T_Name + ''', Modified_Dt from ' + #T_Name + ' order by Modified_Dt desc'
insert #T
exec sp_executesql #SQLT
fetch next from c into #T_Name
end
close c
deallocate c
select * from #T where M >= dateadd(day,datediff(day,0,getdate()),0)
Here is an answer without cursor or temporary table
DECLARE #ColumnName AS nvarchar(40) = 'Modified_Dt';
DECLARE #ModifiedSince AS datetime = '20140709';
DECLARE #sql AS nvarchar(max) = '';
-- Build a query with UNION ALL between all tables containing #ColumnName
WITH AllTables AS (
SELECT SCHEMA_NAME(Tables.schema_id) AS SchemaName
,Tables.name AS TableName
,Columns.name AS ColumnName
FROM sys.tables AS Tables
INNER JOIN sys.columns AS Columns
ON Tables.object_id = Columns.object_id
WHERE Columns.name = #ColumnName
)
SELECT #sql = #sql +
'UNION ALL SELECT ' + QUOTENAME(TableName, '''') +
', ' + QUOTENAME(ColumnName) +
' FROM ' + QUOTENAME(TableName) + CHAR(13)
FROM AllTables;
-- Create a query which selects last change from all tables
SET #sql =
'WITH AllChanges(TableName, ModifiedTime) AS ( ' +
STUFF(#sql, 1, LEN('UNION ALL'), '') + -- Remove first UNION
') ' +
'SELECT TableName ' +
' ,MAX(ModifiedTime) ' +
'FROM AllChanges ' +
'WHERE ModifiedTime > #ModifiedSince '
'GROUP BY TableName '
EXECUTE sp_executesql #sql, N'#ModifiedSince datetime', #ModifiedSince

sp_MSforeachtable to execute procedure on each table

I want to print some dynamic query to execute a procedure on all tables in the database. This is what I've written so far -
EXEC SP_MSFOREACHTABLE '
IF EXISTS(SELECT * FROM INFORMATION_SCHEMA.COLUMNS
WHERE COLUMN_NAME="EMAIL_S" AND TABLE_NAME=PARSENAME("?",1))
BEGIN
PRINT ''EXEC DROPCONSTANT #TBLNAME=''+PARSENAME("?",1)
+'', #FLDNAME=''''EMAIL_S'''' ''
PRINT CHAR(10)+CHAR(13)
END
'
The output is not what I expect it to be -
EXEC DROPCONSTANT #TBLNAME=bill, #FLDNAME='EMAIL_S'
But what I really want it -
EXEC DROPCONSTANT #TBLNAME='bill', #FLDNAME='EMAIL_S'
How about this instead:
DECLARE #output NVARCHAR(MAX) = N'';
SELECT #output += CHAR(13) + CHAR(10)
+ 'EXEC DROPCONSTANT #TBLNAME=''' + t.name + ''','
+ '#FLDNAME=''EMAIL_S'';'
FROM sys.tables AS t
INNER JOIN sys.columns AS c
ON t.[object_id] = c.[object_id]
WHERE c.name = 'EMAIL_S';
SELECT #output;
-- EXEC sp_executesql #output;
You need to add a bunch of '.
PRINT ''DROPCONSTANT #TBLNAME=''''''+PARSENAME("?",1)+'''''', #FLDNAME=''''EMAIL_S'''' ''

Search for a string in all tables, rows and columns of a DB

I am lost in a big database and I am not able to find where the data I get comes from. I was wondering if it is possible with SQL Server 2005 to search for a string in all tables, rows and columns of a database?
Does anybody has an idea if it is possible and how?
This code should do it in SQL 2005, but a few caveats:
It is RIDICULOUSLY slow. I tested it on a small database that I have with only a handful of tables and it took many minutes to complete. If your database is so big that you can't understand it then this will probably be unusable anyway.
I wrote this off the cuff. I didn't put in any error handling and there might be some other sloppiness especially since I don't use cursors often. For example, I think there's a way to refresh the columns cursor instead of closing/deallocating/recreating it every time.
If you can't understand the database or don't know where stuff is coming from, then you should probably find someone who does. Even if you can find where the data is, it might be duplicated somewhere or there might be other aspects of the database that you don't understand. If no one in your company understands the database then you're in a pretty big mess.
DECLARE
#search_string VARCHAR(100),
#table_name SYSNAME,
#table_schema SYSNAME,
#column_name SYSNAME,
#sql_string VARCHAR(2000)
SET #search_string = 'Test'
DECLARE tables_cur CURSOR FOR SELECT TABLE_SCHEMA, TABLE_NAME FROM INFORMATION_SCHEMA.TABLES WHERE TABLE_TYPE = 'BASE TABLE'
OPEN tables_cur
FETCH NEXT FROM tables_cur INTO #table_schema, #table_name
WHILE (##FETCH_STATUS = 0)
BEGIN
DECLARE columns_cur CURSOR FOR SELECT COLUMN_NAME FROM INFORMATION_SCHEMA.COLUMNS WHERE TABLE_SCHEMA = #table_schema AND TABLE_NAME = #table_name AND COLLATION_NAME IS NOT NULL -- Only strings have this and they always have it
OPEN columns_cur
FETCH NEXT FROM columns_cur INTO #column_name
WHILE (##FETCH_STATUS = 0)
BEGIN
SET #sql_string = 'IF EXISTS (SELECT * FROM ' + QUOTENAME(#table_schema) + '.' + QUOTENAME(#table_name) + ' WHERE ' + QUOTENAME(#column_name) + ' LIKE ''%' + #search_string + '%'') PRINT ''' + QUOTENAME(#table_schema) + '.' + QUOTENAME(#table_name) + ', ' + QUOTENAME(#column_name) + ''''
EXECUTE(#sql_string)
FETCH NEXT FROM columns_cur INTO #column_name
END
CLOSE columns_cur
DEALLOCATE columns_cur
FETCH NEXT FROM tables_cur INTO #table_schema, #table_name
END
CLOSE tables_cur
DEALLOCATE tables_cur
I’d suggest you find yourself a 3rd party tool for this such as ApexSQL Search (there are probably others out there too but I use this one because it’s free).
If you really want to go the SQL way you can try using stored procedure created by
Sorna Kumar Muthuraj – copied code is below. Just execute this stored procedure for all tables in your schema (easy with dynamics SQL)
CREATE PROCEDURE SearchTables
#Tablenames VARCHAR(500)
,#SearchStr NVARCHAR(60)
,#GenerateSQLOnly Bit = 0
AS
/*
Parameters and usage
#Tablenames -- Provide a single table name or multiple table name with comma seperated.
If left blank , it will check for all the tables in the database
#SearchStr -- Provide the search string. Use the '%' to coin the search.
EX : X%--- will give data staring with X
%X--- will give data ending with X
%X%--- will give data containig X
#GenerateSQLOnly -- Provide 1 if you only want to generate the SQL statements without seraching the database.
By default it is 0 and it will search.
Samples :
1. To search data in a table
EXEC SearchTables #Tablenames = 'T1'
,#SearchStr = '%TEST%'
The above sample searches in table T1 with string containing TEST.
2. To search in a multiple table
EXEC SearchTables #Tablenames = 'T2'
,#SearchStr = '%TEST%'
The above sample searches in tables T1 & T2 with string containing TEST.
3. To search in a all table
EXEC SearchTables #Tablenames = '%'
,#SearchStr = '%TEST%'
The above sample searches in all table with string containing TEST.
4. Generate the SQL for the Select statements
EXEC SearchTables #Tablenames = 'T1'
,#SearchStr = '%TEST%'
,#GenerateSQLOnly = 1
*/
SET NOCOUNT ON
DECLARE #CheckTableNames Table
(
Tablename sysname
)
DECLARE #SQLTbl TABLE
(
Tablename SYSNAME
,WHEREClause VARCHAR(MAX)
,SQLStatement VARCHAR(MAX)
,Execstatus BIT
)
DECLARE #sql VARCHAR(MAX)
DECLARE #tmpTblname sysname
IF LTRIM(RTRIM(#Tablenames)) IN ('' ,'%')
BEGIN
INSERT INTO #CheckTableNames
SELECT Name
FROM sys.tables
END
ELSE
BEGIN
SELECT #sql = 'SELECT ''' + REPLACE(#Tablenames,',',''' UNION SELECT ''') + ''''
INSERT INTO #CheckTableNames
EXEC(#sql)
END
INSERT INTO #SQLTbl
( Tablename,WHEREClause)
SELECT SCh.name + '.' + ST.NAME,
(
SELECT '[' + SC.name + ']' + ' LIKE ''' + #SearchStr + ''' OR ' + CHAR(10)
FROM SYS.columns SC
JOIN SYS.types STy
ON STy.system_type_id = SC.system_type_id
AND STy.user_type_id =SC.user_type_id
WHERE STY.name in ('varchar','char','nvarchar','nchar')
AND SC.object_id = ST.object_id
ORDER BY SC.name
FOR XML PATH('')
)
FROM SYS.tables ST
JOIN #CheckTableNames chktbls
ON chktbls.Tablename = ST.name
JOIN SYS.schemas SCh
ON ST.schema_id = SCh.schema_id
WHERE ST.name <> 'SearchTMP'
GROUP BY ST.object_id, SCh.name + '.' + ST.NAME ;
UPDATE #SQLTbl
SET SQLStatement = 'SELECT * INTO SearchTMP FROM ' + Tablename + ' WHERE ' + substring(WHEREClause,1,len(WHEREClause)-5)
DELETE FROM #SQLTbl
WHERE WHEREClause IS NULL
WHILE EXISTS (SELECT 1 FROM #SQLTbl WHERE ISNULL(Execstatus ,0) = 0)
BEGIN
SELECT TOP 1 #tmpTblname = Tablename , #sql = SQLStatement
FROM #SQLTbl
WHERE ISNULL(Execstatus ,0) = 0
IF #GenerateSQLOnly = 0
BEGIN
IF OBJECT_ID('SearchTMP','U') IS NOT NULL
DROP TABLE SearchTMP
EXEC (#SQL)
IF EXISTS(SELECT 1 FROM SearchTMP)
BEGIN
SELECT Tablename=#tmpTblname,* FROM SearchTMP
END
END
ELSE
BEGIN
PRINT REPLICATE('-',100)
PRINT #tmpTblname
PRINT REPLICATE('-',100)
PRINT replace(#sql,'INTO SearchTMP','')
END
UPDATE #SQLTbl
SET Execstatus = 1
WHERE Tablename = #tmpTblname
END
SET NOCOUNT OFF
go
Although the solutions presented before are valid and work, I humbly offer a code that's cleaner, more elegant, and with better performance, at least as I see it.
Firstly, one may ask: Why would anyone ever need a code snippet to globally and blindly look for a string? Hey, they already invented fulltext, don't you know?
My answer: my mainly work is at systems integration projects, and discovering where the data is written is important whenever I'm learning a new and undocummented database, which seldom happens.
Also, the code I present is a stripped down version of a more powerful and dangerous script that searches and REPLACES text throughout the database.
CREATE TABLE #result(
id INT IDENTITY, -- just for register seek order
tblName VARCHAR(255),
colName VARCHAR(255),
qtRows INT
)
go
DECLARE #toLookFor VARCHAR(255)
SET #toLookFor = '[input your search criteria here]'
DECLARE cCursor CURSOR LOCAL FAST_FORWARD FOR
SELECT
'[' + usr.name + '].[' + tbl.name + ']' AS tblName,
'[' + col.name + ']' AS colName,
LOWER(typ.name) AS typName
FROM
sysobjects tbl
INNER JOIN(
syscolumns col
INNER JOIN systypes typ
ON typ.xtype = col.xtype
)
ON col.id = tbl.id
--
LEFT OUTER JOIN sysusers usr
ON usr.uid = tbl.uid
WHERE tbl.xtype = 'U'
AND LOWER(typ.name) IN(
'char', 'nchar',
'varchar', 'nvarchar',
'text', 'ntext'
)
ORDER BY tbl.name, col.colorder
--
DECLARE #tblName VARCHAR(255)
DECLARE #colName VARCHAR(255)
DECLARE #typName VARCHAR(255)
--
DECLARE #sql NVARCHAR(4000)
DECLARE #crlf CHAR(2)
SET #crlf = CHAR(13) + CHAR(10)
OPEN cCursor
FETCH cCursor
INTO #tblName, #colName, #typName
WHILE ##fetch_status = 0
BEGIN
IF #typName IN('text', 'ntext')
BEGIN
SET #sql = ''
SET #sql = #sql + 'INSERT INTO #result(tblName, colName, qtRows)' + #crlf
SET #sql = #sql + 'SELECT #tblName, #colName, COUNT(*)' + #crlf
SET #sql = #sql + 'FROM ' + #tblName + #crlf
SET #sql = #sql + 'WHERE PATINDEX(''%'' + #toLookFor + ''%'', ' + #colName + ') > 0' + #crlf
END
ELSE
BEGIN
SET #sql = ''
SET #sql = #sql + 'INSERT INTO #result(tblName, colName, qtRows)' + #crlf
SET #sql = #sql + 'SELECT #tblName, #colName, COUNT(*)' + #crlf
SET #sql = #sql + 'FROM ' + #tblName + #crlf
SET #sql = #sql + 'WHERE ' + #colName + ' LIKE ''%'' + #toLookFor + ''%''' + #crlf
END
EXECUTE sp_executesql
#sql,
N'#tblName varchar(255), #colName varchar(255), #toLookFor varchar(255)',
#tblName, #colName, #toLookFor
FETCH cCursor
INTO #tblName, #colName, #typName
END
SELECT *
FROM #result
WHERE qtRows > 0
ORDER BY id
GO
DROP TABLE #result
go
If you are "getting data" from an application, the sensible thing would be to use the profiler and profile the database while running the application. Trace it, then search the results for that string.
The SSMS Tools PACK Add-In (Add-On) for Microsoft SQL Server Management Studio and Microsoft SQL Server Management Studio Express will do exactly what you need. On larger database it takes some time to search, but that is to be expected. It also includes a ton of cool features that should have be included with SQL Server Management Studio in the first place. Give it a try www.ssmstoolspack.com/
You do need to have SP2 for SQL Server Management Studio installed to run the tools.
I adapted a script originally written by Narayana Vyas Kondreddi in 2002. I changed the where clause to check text/ntext fields as well, by using patindex rather than like. I also changed the results table slightly. Unreasonably, I changed variable names, and aligned as I prefer (no disrespect to Mr. Kondretti). The user may want to change the data types searched. I used a global table to allow querying mid-processing, but a permanent table might be a smarter way to go.
/* original script by Narayana Vyas Kondreddi, 2002 */
/* adapted by Oliver Holloway, 2009 */
/* these lines can be replaced by use of input parameter for a proc */
declare #search_string varchar(1000);
set #search_string = 'what.you.are.searching.for';
/* create results table */
create table ##string_locations (
table_name varchar(1000),
field_name varchar(1000),
field_value varchar(8000)
)
;
/* special settings */
set nocount on
;
/* declare variables */
declare
#table_name varchar(1000),
#field_name varchar(1000)
;
/* variable settings */
set #table_name = ''
;
set #search_string = QUOTENAME('%' + #search_string + '%','''')
;
/* for each table */
while #table_name is not null
begin
set #field_name = ''
set #table_name = (
select MIN(QUOTENAME(table_schema) + '.' + QUOTENAME(table_name))
from INFORMATION_SCHEMA.TABLES
where
table_type = 'BASE TABLE' and
QUOTENAME(table_schema) + '.' + QUOTENAME(table_name) > #table_name and
OBJECTPROPERTY(OBJECT_ID(QUOTENAME(table_schema) + '.' + QUOTENAME(table_name)), 'IsMSShipped') = 0
)
/* for each string-ish field */
while (#table_name is not null) and (#field_name is not null)
begin
set #field_name = (
select MIN(QUOTENAME(column_name))
from INFORMATION_SCHEMA.COLUMNS
where
table_schema = PARSENAME(#table_name, 2) and
table_name = PARSENAME(#table_name, 1) and
data_type in ('char', 'varchar', 'nchar', 'nvarchar', 'text', 'ntext') and
QUOTENAME(column_name) > #field_name
)
/* search that field for the string supplied */
if #field_name is not null
begin
insert into ##string_locations
exec(
'select ''' + #table_name + ''',''' + #field_name + ''',' + #field_name +
'from ' + #table_name + ' (nolock) ' +
'where patindex(' + #search_string + ',' + #field_name + ') > 0' /* patindex works with char & text */
)
end
;
end
;
end
;
/* return results */
select table_name, field_name, field_value from ##string_locations (nolock)
;
/* drop temp table */
--drop table ##string_locations
;
Other answers posted already may work equally well or better, but I haven't used them. However, the following SQL I have used, and it really helped me out when I was trying to reverse-engineer a big system with a huge (and very unorganzied) SQL Server database.
This isn't my code. I wish I could credit the original author, but I can't find the link to the article anymore :(
Use
go
declare #SearchChar varchar(8000)
Set #SearchChar = -- Like 'A%', '11/11/2006'
declare #CMDMain varchar(8000), #CMDMainCount varchar(8000),#CMDJoin varchar(8000)
declare #ColumnName varchar(100),#TableName varchar(100)
declare dbTable cursor for
SELECT
Distinct b.Name as TableName
FROM
sysobjects b
WHERE
b.type='u' and b.Name 'dtproperties'
order by b.name
open dbTable
fetch next from dbTable into #TableName
WHILE ##FETCH_STATUS = 0
BEGIN
declare db cursor for
SELECT
c.Name as ColumnName
FROM
sysobjects b,
syscolumns c
WHERE
C.id = b.id and
b.type='u' and b.Name = #TableName
order by b.name
open db
fetch next from db into #ColumnName
set #CMDMain = 'SELECT ' + char(39) + #TableName + char(39) + ' as TableName,'+
' ['+ #TableName + '].* FROM [' + #TableName + ']'+
' WHERE '
set #CMDMainCount = 'SELECT Count(*) FROM [' + #TableName + '] Where '
Set #CMDJoin = ''
WHILE ##FETCH_STATUS = 0
BEGIN
set #CMDJoin = #CMDJoin + 'Convert(varchar(5000),[' +#ColumnName + ']) like ' + char(39) + #SearchChar + char(39) + ' OR '
fetch next from db into #ColumnName
end
close db
deallocate db
Set #CMDMainCount = 'If ('+ #CMDMainCount + Left(#CMDJoin, len(#CMDJoin) - 3)+ ') > 0 Begin '
Set #CMDMain = #CMDMainCount + #CMDMain + Left(#CMDJoin, len(#CMDJoin) - 3)
Set #CMDMain = #CMDMain + ' End '
Print #CMDMain
exec (#CMDMain)
fetch next from dbTable into #TableName
end
close dbTable
deallocate dbTable
Actually Im agree with MikeW (+1) it's better to use profiler for this case.
Anyway, if you really need to grab all (n)varchar columns in db and make a search. See below.
I suppose to use INFORMATION_SCHEMA.Tables + dynamic SQL.
The plain search:
DECLARE #SearchText VARCHAR(100)
SET #SearchText = '12'
DECLARE #Tables TABLE(N INT, TableName VARCHAR(100), ColumnNamesCSV VARCHAR(2000), SQL VARCHAR(4000))
INSERT INTO #Tables (TableName, ColumnNamesCSV)
SELECT T.TABLE_NAME AS TableName,
( SELECT C.Column_Name + ','
FROM INFORMATION_SCHEMA.Columns C
WHERE T.TABLE_NAME = C.TABLE_NAME
AND C.DATA_TYPE IN ('nvarchar','varchar')
FOR XML PATH('')
)
FROM INFORMATION_SCHEMA.Tables T
DELETE FROM #Tables WHERE ColumnNamesCSV IS NULL
INSERT INTO #Tables (N, TableName, ColumnNamesCSV)
SELECT ROW_NUMBER() OVER(ORDER BY TableName), TableName, ColumnNamesCSV
FROM #Tables
DELETE FROM #Tables WHERE N IS NULL
UPDATE #Tables
SET ColumnNamesCSV = SUBSTRING(ColumnNamesCSV, 0, LEN(ColumnNamesCSV))
UPDATE #Tables
SET SQL = 'SELECT * FROM ['+TableName+'] WHERE '''+#SearchText+''' IN ('+ColumnNamesCSV+')'
DECLARE #C INT,
#I INT,
#SQL VARCHAR(4000)
SELECT #I = 1,
#C = COUNT(1)
FROM #Tables
WHILE #I <= #C BEGIN
SELECT #SQL = SQL FROM #Tables WHERE N = #I
SET #I = #I+1
EXEC(#SQL)
END
and one with LIKE clause:
DECLARE #SearchText VARCHAR(100)
SET #SearchText = '12'
DECLARE #Tables TABLE(N INT, TableName VARCHAR(100), ColumnNamesCSVLike VARCHAR(2000), LIKESQL VARCHAR(4000))
INSERT INTO #Tables (TableName, ColumnNamesCSVLike)
SELECT T.TABLE_NAME AS TableName,
( SELECT C.Column_Name + ' LIKE ''%'+#SearchText+'%'' OR '
FROM INFORMATION_SCHEMA.Columns C
WHERE T.TABLE_NAME = C.TABLE_NAME
AND C.DATA_TYPE IN ('nvarchar','varchar')
FOR XML PATH(''))
FROM INFORMATION_SCHEMA.Tables T
DELETE FROM #Tables WHERE ColumnNamesCSVLike IS NULL
INSERT INTO #Tables (N, TableName, ColumnNamesCSVLike)
SELECT ROW_NUMBER() OVER(ORDER BY TableName), TableName, ColumnNamesCSVLike
FROM #Tables
DELETE FROM #Tables WHERE N IS NULL
UPDATE #Tables
SET ColumnNamesCSVLike = SUBSTRING(ColumnNamesCSVLike, 0, LEN(ColumnNamesCSVLike)-2)
UPDATE #Tables SET LIKESQL = 'SELECT * FROM ['+TableName+'] WHERE '+ColumnNamesCSVLike
DECLARE #C INT,
#I INT,
#LIKESQL VARCHAR(4000)
SELECT #I = 1,
#C = COUNT(1)
FROM #Tables
WHILE #I <= #C BEGIN
SELECT #LIKESQL = LIKESQL FROM #Tables WHERE N = #I
SET #I = #I +1
EXEC(#LIKESQL)
END
#NLwino, yery good query with a few errors for keyword usage. I had to modify it a little to wrap the keywords with [ ] and also look char and ntext columns.
DECLARE #searchstring NVARCHAR(255)
SET #searchstring = '%WDB1014%'
DECLARE #sql NVARCHAR(max)
SELECT #sql = STUFF((
SELECT ' UNION ALL SELECT ''' + TABLE_NAME + ''' AS tbl, ''' + COLUMN_NAME + ''' AS col, [' + COLUMN_NAME + '] AS val' +
' FROM ' + TABLE_SCHEMA + '.[' + TABLE_NAME +
'] WHERE [' + COLUMN_NAME + '] LIKE ''' + #searchstring + ''''
FROM INFORMATION_SCHEMA.COLUMNS
WHERE DATA_TYPE in ('nvarchar', 'varchar', 'char', 'ntext')
FOR XML PATH('')
) ,1, 11, '')
Exec (#sql)
I ran it on 2.5 GB database and it came back in 51 seconds
I think this can be an easiest way to find a string in all rows of your database -without using cursors and FOR XML-.
CREATE PROCEDURE SPFindAll (#find VARCHAR(max) = '')
AS
BEGIN
SET NOCOUNT ON;
--
DECLARE #query VARCHAR(max) = ''
SELECT #query = #query +
CASE
WHEN #query = '' THEN ''
ELSE ' UNION ALL '
END +
'SELECT ''' + s.name + ''' As schemaName, ''' + t.name + ''' As tableName, ''' + c.name + ''' As ColumnName, [' + c.name + '] COLLATE DATABASE_DEFAULT As [Data] FROM [' + s.name + '].[' + t.name + '] WHERE [' + c.name + '] Like ''%' + #find + '%'''
FROM
sys.schemas s
INNER JOIN
sys.tables t ON s.[schema_id] = t.[schema_id]
INNER JOIN
sys.columns c ON t.[object_id] = c.[object_id]
INNER JOIN
sys.types ty ON c.user_type_id = ty.user_type_id
WHERE
ty.name LIKE '%char'
EXEC(#query)
END
By creating this stored procedure you can run it for any string you want to find like this:
EXEC SPFindAll 'Hello World'
The result will be like this:
schemaName | tableName | columnName | Data
-----------+-----------+------------+-----------------------
schema1 | Table1 | Column1 | Hello World
schema1 | Table1 | Column1 | Hello World!
schema1 | Table2 | Column1 | I say "Hello World".
schema1 | Table2 | Column2 | Hello World
This uses no cursors or anything like that, just one dynamic query.
Also note that this uses LIKE. Since that happened to be what I needed. It works for all schemas, all tables and only query's those columns that are NVARCHAR or VARCHAR even if they have UDDT.
DECLARE #searchstring NVARCHAR(255)
SET #searchstring = '%searchstring%'
DECLARE #sql NVARCHAR(max)
SELECT #sql = STUFF((
SELECT ' UNION ALL SELECT ''' + TABLE_NAME + ''' AS tablename, ''' + COLUMN_NAME + ''' AS columnname, ' + COLUMN_NAME + ' AS valuename' +
' FROM ' + TABLE_SCHEMA + '.' + TABLE_NAME +
' WHERE ' + COLUMN_NAME + ' LIKE ''' + #searchstring + ''''
FROM INFORMATION_SCHEMA.COLUMNS
WHERE DATA_TYPE in ('nvarchar', 'varchar')
FOR XML PATH('')
) ,1, 11, '')
EXEC(#sql)
The output gives you the table, column and value. Time to execute on a small database was ~3 seconds, had about 3000 results.
/*
This procedure is for finding any string or date in all tables
if search string is date, its format should be yyyy-MM-dd
eg. 2011-07-05
*/
-- ================================================
-- Exec SearchInTables 'f6f56934-a5d4-4967-80a1-1a2223b9c7b1'
-- ================================================
SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO
-- =============================================
-- Author: <Joshy,,Name>
-- Create date: <Create Date,,>
-- Description: <Description,,>
-- =============================================
ALTER PROCEDURE SearchInTables
#myValue nvarchar(1000)
AS
BEGIN
-- SET NOCOUNT ON added to prevent extra result sets from
-- interfering with SELECT statements.
SET NOCOUNT ON;
-- Insert statements for procedure here
DECLARE #searchsql nvarchar(max)
DECLARE #table_name nvarchar(1000)
DECLARE #Schema_name nvarchar(1000)
DECLARE #ParmDefinition nvarchar(500)
DECLARE #XMLIn nvarchar(max)
SET #ParmDefinition = N'#XMLOut varchar(max) OUTPUT'
SELECT A.name,b.name
FROM sys.tables A
INNER JOIN sys.schemas B ON A.schema_id=B.schema_id
WHERE A.name like 'tbl_Tax_Sections'
DECLARE tables_cur CURSOR FOR
SELECT A.name,b.name FOM sys.tables A
INNER JOIN sys.schemas B ON A.schema_id=B.schema_id
WHERE A.type = 'U'
OPEN tables_cur
FETCH NEXT FROM tables_cur INTO #table_name , #Schema_name
WHILE (##FETCH_STATUS = 0)
BEGIN
SET #searchsql ='SELECT #XMLOut=(SELECT PATINDEX(''%'+ #myValue+ '%'''
SET #searchsql =#searchsql + ', (SELECT * FROM '+#Schema_name+'.'+#table_name+' FOR XML AUTO) ))'
--print #searchsql
EXEC sp_executesql #searchsql, #ParmDefinition, #XMLOut=#XMLIn OUTPUT
--print #XMLIn
IF #XMLIn <> 0 PRINT #Schema_name+'.'+#table_name
FETCH NEXT FROM tables_cur INTO #table_name , #Schema_name
END
CLOSE tables_cur
DEALLOCATE tables_cur
RETURN
END
GO
To "find where the data I get comes from", you can start SQL Profiler, start your report or application, and you will see all the queries issued against your database.
Or, you can use my query here, should be simpler then having to create sProcs for each DB you want to search: FullParam SQL Blog
/* 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
This query can do the thing for you.
DECLARE
#search_string VARCHAR(100),
#table_name SYSNAME,
#table_id INT,
#column_name SYSNAME,
#sql_string VARCHAR(2000)
SET #search_string = 'StringtoSearch'
DECLARE tables_cur CURSOR FOR SELECT ss.name +'.'+ so.name [name], object_id FROM sys.objects so INNER JOIN sys.schemas ss ON so.schema_id = ss.schema_id WHERE type = 'U'
OPEN tables_cur
FETCH NEXT FROM tables_cur INTO #table_name, #table_id
WHILE (##FETCH_STATUS = 0)
BEGIN
DECLARE columns_cur CURSOR FOR SELECT name FROM sys.columns WHERE object_id = #table_id
AND system_type_id IN (167, 175, 231, 239, 99)
OPEN columns_cur
FETCH NEXT FROM columns_cur INTO #column_name
WHILE (##FETCH_STATUS = 0)
BEGIN
SET #sql_string = 'IF EXISTS (SELECT * FROM ' + #table_name + ' WHERE [' + #column_name + ']
LIKE ''%' + #search_string + '%'') PRINT ''' + #table_name + ', ' + #column_name + ''''
EXECUTE(#sql_string)
FETCH NEXT FROM columns_cur INTO #column_name
END
CLOSE columns_cur
DEALLOCATE columns_cur
FETCH NEXT FROM tables_cur INTO #table_name, #table_id
END
CLOSE tables_cur
DEALLOCATE tables_cur