SQL : Select a table name containing specific string [duplicate] - sql

This question already has answers here:
Find a value anywhere in a database
(18 answers)
Search all tables, all columns for a specific value SQL Server [duplicate]
(4 answers)
Closed 5 years ago.
Suppose I have string to search "Sample String" and I have 100 tables in my database.
I want to search if any of the table contains this string.
Eg. If tlbSample contains string "Sample String" then it should show it.
I tried :-
SELECT name
FROM sys.tables
WHERE name LIKE '%Sample String%'
But no luck.
Please help me.

You can use this. I have copied it from here : https://stackoverflow.com/a/13588431/400447
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

Related

Dynamic SQL - Insert a variables via INSERT INTO x SELECT statement

I would like to ask how can I insert a variables into a table using INSERT INTO x SELECT statement via dynamic SQL.
I have following table:
|-------------------|-----------------|--------------|-----------------|
| TableName | ColName | Value | SQL_Statement |
|-------------------|-----------------|--------------|-----------------|
I get a content for Value column by this query:
INSERT INTO #ReturnTable(Value) SELECT TreeHolder FROM prm.Schm_Root WHERE ParentTreeHolderId = 'DD040D31-4591-4658-A02E-A6ED00AB64F2';
But I need to fill whole table. Please consider that other values are variables, not SQL queries.
SELECT #TableSchema = TableSchema FROM #TableNames WHERE Id = #Counter;
SELECT #TableName = TableName FROM #TableNames WHERE Id = #Counter;
SELECT #ColName = ColName FROM #TableNames WHERE Id = #Counter;
SET #SQL_Statement = 'SELECT ' + #ColName + ' FROM ' + #TableSchema + '.' + #TableName + ' WHERE ' + #ColName + ' = ' + '''''' + CAST(#GuidArgument AS NVARCHAR(50)) + '''''' + ';';
Now I have this query that fills a table:
SET #SQL_String = N'INSERT INTO #ReturnTable SELECT
''' + #TableName + ''',
''' + #ColName + ''',
''' + #SQL_Statement + ''',
'' + Value + '',
(SELECT ' +
#ColName + '
FROM ' +
#TableSchema + '.' + #TableName + '
WHERE ' +
#ColName + ' = ''' + CAST(#GuidArgument AS NVARCHAR(50)) + '
'')';
EXECUTE sp_executesql #SQL_String
PRINT #SQL_String;
The thing I need is to rewrite this query from INSERT INTO ? VALUE to INSERT INTO ? SELECT format.
If I understand correctly, you want to insert SQL execute syntax string and it results in ReturnTable table.
I would let subquery SQL execute syntax save in a variable. because the will be more clear what you need to do.
Declare a new variable #SQL_excuteStatement variable to save your execute syntax.
the #SQL_Statement to carry the original SQL string.
set #SQL_Statement = 'SELECT ' + #ColName +
' FROM ' + #TableSchema + '.' + #TableName +
' WHERE ' + #ColName + ' = '+'''''' + CAST(#GuidArgument AS NVARCHAR(50)) + '''''';
and use select ... from table instead of subquery in select
There is a sample for you.
DECLARE #SQL_String NVARCHAR(MAX)
DECLARE #TableSchema NVARCHAR(MAX)
DECLARE #TableName NVARCHAR(MAX)
DECLARE #ColName NVARCHAR(MAX)
DECLARE #Counter int = 1
DECLARE #SQL_Statement NVARCHAR(MAX)
DECLARE #GuidArgument INT = 1
CREATE TABLE TableNames(
ID INT,
TableSchema NVARCHAR(100),
TableName NVARCHAR(100),
ColName NVARCHAR(100)
);
CREATE TABLE ReturnTable(
TableName NVARCHAR(100),
ColName NVARCHAR(100),
SQL_Statement NVARCHAR(max),
value nvarchar(max)
);
INSERT INTO TableNames VALUES (1,'dbo','T','val');
CREATE TABLE T(val INT);
INSERT INTO T VALUES (1)
SELECT #TableSchema = TableSchema FROM TableNames WHERE Id = #Counter;
SELECT #TableName = TableName FROM TableNames WHERE Id = #Counter;
SELECT #ColName = ColName FROM TableNames WHERE Id = #Counter;
set #SQL_Statement = 'SELECT ' + #ColName +
' FROM ' + #TableSchema + '.' + #TableName +
' WHERE ' + #ColName + ' = '+ '''''' + CAST(#GuidArgument AS NVARCHAR(50)) + '''''';
SET #SQL_String = N'INSERT INTO ReturnTable (TableName,ColName,SQL_Statement,value)
SELECT '''+ #TableName + ''','''+ #ColName + ''','''+ #SQL_Statement + '''' + ',' + QUOTENAME(#ColName) +
' FROM ' + QUOTENAME(#TableSchema) + '.' + QUOTENAME(#TableName) + '' +
' WHERE ' + #ColName + ' = ''' + CAST(#GuidArgument AS NVARCHAR(50)) + '''';
EXECUTE sp_executesql #SQL_String
sqlfiddle
Note
I would suggest you use clear column after insert into
INSERT INTO table2 (column1, column2, column3, ...)
SELECT column1, column2, column3, ...
FROM table1
WHERE condition;

Generate insert statement which has same columns of a table in SQL Server

I have wide table with 100 columns.
I need a SP which takes 100 parameters and then does the insert.
I know how to do this manually. But having the table definition and knowing that SP parameters will have exact same name of the table columns, can you think of a better/faster way to generate this stored procedure?
I use SQL to write it for you. Check it out and let me know if it needs any tweaks or if you have any questions.
IF OBJECT_ID('yourTable') IS NOT NULL
DROP TABLE yourTable;
CREATE TABLE yourTable
(
col1 INT,
col2 VARCHAR(100),
col3 NUMERIC(18,2)
)
DECLARE #InputParams VARCHAR(MAX),
#InsertColumns VARCHAR(MAX),
#InsertParams VARCHAR(MAX);
WITH CTE_columns
AS
(
SELECT COLUMN_NAME,
UPPER(DATA_TYPE) data_type,
'(' + CAST(CHARACTER_MAXIMUM_LENGTH AS VARCHAR(10)) + ')' max_length,
CASE
WHEN DATA_TYPE IN ('Numeric','Decimal') THEN CONCAT('(',NUMERIC_PRECISION,',',NUMERIC_SCALE,')')
END prec_scale
--#InsertColumns = COALESCE(#InsertColumns + ',','') + COLUMN_NAME,
FROM INFORMATION_SCHEMA.COLUMNS A
WHERE TABLE_NAME = 'yourTable'
)
SELECT #InputParams = COALESCE(#InputParams + ',','') + CONCAT('#',column_name,' ',data_type,max_length,prec_scale),
#InsertColumns = COALESCE(#InsertColumns + ',','') + COLUMN_NAME,
#InsertParams = COALESCE(#InsertParams + ',','') + '#'+ COLUMN_NAME
FROM CTE_columns
SELECT
'CREATE PROCEDURE dbo.yourProc ' + #InputParams +
' AS
INSERT INTO yourTable(' + #InsertColumns + ')
VALUES (' + #InsertParams + ');
GO'
Results(Formatting isn't great, but it works):
CREATE PROCEDURE dbo.yourProc #col1 INT,#col2 VARCHAR(100),#col3 NUMERIC(18,2) AS
INSERT INTO yourTable(col1,col2,col3)
VALUES (#col1,#col2,#col3);
GO
For this type of scenario, I like to leverage table types.
First, create the table type:
CREATE TYPE [YourType] AS TABLE (columns...)
In C#, populate a DataTable "template" by running this query (using a DataAdapter):
DECLARE #tt AS [YourType]
SELECT * FROM #tt
Then add a row to the table and cycle through the columns to add the necessary values.
Then pass the datatable as a parameter into your procedure:
CREATE PROCEDURE [YourProc]
#tt [YourType] READONLY
AS
BEGIN
--do stuff
END
An added benefit of this approach is that you can pass multiple records into the procedure with a single call.
You can probably quickly modify this for your needs:
Declare #tableName nvarchar(100) = 'aspnet_Membership'
Declare #objectName nvarchar(100) = 'Membership'
DECLARE #newLineChar AS CHAR(2) = CHAR(13) + CHAR(10)
Declare #columnName nvarchar(50)
Declare #dataType nvarchar(50)
Declare #characterLength int
Declare #isNullableString varchar(3)
Declare #ordinalPosition int
Declare #firstSortOrder smallint
Declare #variableTableCreateCode nvarchar(max) = ''
Declare #variableTableDataTypeCode nvarchar(128)
Declare #variableTableSelectCode001 nvarchar(max) = ''
Declare #variableTableSelectCode002 nvarchar(max) = ''
Declare #varableTableInsertIntoCode nvarchar(max) = ''
Declare tbl_ColumnCursor Cursor For
Select colSchema.COLUMN_NAME, colSchema.DATA_TYPE, colSchema.CHARACTER_MAXIMUM_LENGTH, colSchema.IS_NULLABLE , colSchema.ORDINAL_POSITION , FirstSortOrder = CASE WHEN PrimaryKeyDerived.CONSTRAINT_TYPE IS NOT NULL THEN 1 ELSE 2 END
from INFORMATION_SCHEMA.COLUMNS colSchema
LEFT JOIN
(
SELECT
INFORMATION_SCHEMA.COLUMNS.TABLE_NAME
,INFORMATION_SCHEMA.COLUMNS.COLUMN_NAME
,INFORMATION_SCHEMA.TABLE_CONSTRAINTS.CONSTRAINT_TYPE
FROM INFORMATION_SCHEMA.COLUMNS
LEFT OUTER JOIN information_schema.KEY_COLUMN_USAGE
ON
INFORMATION_SCHEMA.COLUMNS.TABLE_NAME=information_schema.KEY_COLUMN_USAGE.TABLE_NAME
AND INFORMATION_SCHEMA.COLUMNS.COLUMN_NAME=information_schema.KEY_COLUMN_USAGE.COLUMN_NAME
LEFT OUTER JOIN INFORMATION_SCHEMA.TABLE_CONSTRAINTS
ON
information_schema.KEY_COLUMN_USAGE.TABLE_NAME=information_schema.TABLE_CONSTRAINTS.TABLE_NAME
AND information_schema.KEY_COLUMN_USAGE.CONSTRAINT_NAME=information_schema.TABLE_CONSTRAINTS.CONSTRAINT_NAME
WHERE CONSTRAINT_TYPE = 'PRIMARY KEY'
) as PrimaryKeyDerived on colSchema.TABLE_NAME = PrimaryKeyDerived.TABLE_NAME and colSchema.COLUMN_NAME = PrimaryKeyDerived.COLUMN_NAME
where colSchema.TABLE_NAME = #tableName
Order By FirstSortOrder , colSchema.ORDINAL_POSITION
Set #variableTableCreateCode = 'declare #' + #objectName + 'Holder table ( ' + #objectName + 'SurrogateKey int , '
Set #variableTableSelectCode001 = 'INSERT INTO #' + #objectName + 'Holder ( '
Set #variableTableSelectCode002 = ' SELECT '
Set #varableTableInsertIntoCode = 'INSERT INTO '+#tableName+' ( '
Open tbl_ColumnCursor
Fetch Next From tbl_ColumnCursor Into #ColumnName, #dataType, #characterLength, #isNullableString, #ordinalPosition , #firstSortOrder
While ##FETCH_STATUS = 0
Begin
print '/#ColumnName/'
print #ColumnName
print ''
print '/##dataType/'
print #dataType
print ''
print '/###isNullableString/'
print #isNullableString
print ''
Select #variableTableDataTypeCode =
case
when #dataType like '%char%' and #characterLength = -1 Then
#dataType+'(max)'
when #dataType like '%char%' and #characterLength = 1 Then
#dataType+'('+convert(varchar(32), #characterLength)+')'
When (#dataType like '%char%') Or (#dataType = 'xml') Or (#dataType like '%text%') Then
#dataType+'('+convert(varchar(32), #characterLength)+')'
Else #dataType
End
Set #variableTableCreateCode = #variableTableCreateCode + ' [' + #columnName + '] ' + #variableTableDataTypeCode +','
select #variableTableSelectCode002 = #variableTableSelectCode002 + 'T.MyEntity.value(''#' + #columnName + ''', '''+#variableTableDataTypeCode+''') AS ' + #columnName + ','
Fetch Next From tbl_ColumnCursor Into #ColumnName, #dataType, #characterLength , #isNullableString , #ordinalPosition , #firstSortOrder
End
Close tbl_ColumnCursor
Deallocate tbl_ColumnCursor
if(DATALENGTH(#variableTableCreateCode) > 0)
BEGIN
select #variableTableCreateCode = LEFT(#variableTableCreateCode, LEN(#variableTableCreateCode) -1)
END
if(DATALENGTH(#variableTableSelectCode002) > 0)
BEGIN
select #variableTableSelectCode002 = LEFT(#variableTableSelectCode002, LEN(#variableTableSelectCode002) -1)
END
Set #variableTableCreateCode = #variableTableCreateCode + #newLineChar + ' ) '
select #variableTableCreateCode
select #variableTableSelectCode001 = #variableTableSelectCode001 + ( SELECT
MyColumns = STUFF
(
(
SELECT ', [' + r.COLUMN_NAME + ']'
FROM INFORMATION_SCHEMA.COLUMNS AS r
WHERE r.TABLE_NAME = tabs.TABLE_NAME
ORDER BY r.ORDINAL_POSITION
FOR XML PATH(''), TYPE
).value('.[1]','nvarchar(max)'),
1,1,''
)
FROM INFORMATION_SCHEMA.TABLES AS tabs
/* Optional WHERE Clause */
WHERE
tabs.TABLE_NAME = #tableName
)
select #variableTableSelectCode001 = #variableTableSelectCode001 + ' ) '+#newLineChar
select #variableTableSelectCode002 = #variableTableSelectCode002 + ' FROM #xmldata.nodes(''RootElement/' + #tableName + 'Elements/' + #tableName + 'Element'') AS T(MyEntity); '
select #variableTableSelectCode001 + #variableTableSelectCode002
select #varableTableInsertIntoCode = #varableTableInsertIntoCode + ( SELECT
MyColumns = STUFF
(
(
SELECT ', [' + r.COLUMN_NAME + ']'
FROM INFORMATION_SCHEMA.COLUMNS AS r
WHERE r.TABLE_NAME = tabs.TABLE_NAME
ORDER BY r.ORDINAL_POSITION
FOR XML PATH(''), TYPE
).value('.[1]','nvarchar(max)'),
1,1,''
)
FROM INFORMATION_SCHEMA.TABLES AS tabs
WHERE
tabs.TABLE_NAME = #tableName
)
select #varableTableInsertIntoCode = #varableTableInsertIntoCode + ' ) SELECT '
select #varableTableInsertIntoCode = #varableTableInsertIntoCode + ( SELECT
MyColumns = STUFF
(
(
SELECT ', holder.[' + r.COLUMN_NAME + ']'
FROM INFORMATION_SCHEMA.COLUMNS AS r
WHERE r.TABLE_NAME = tabs.TABLE_NAME
ORDER BY r.ORDINAL_POSITION
FOR XML PATH(''), TYPE
).value('.[1]','nvarchar(max)'),
1,1,''
)
FROM INFORMATION_SCHEMA.TABLES AS tabs
WHERE
tabs.TABLE_NAME = #tableName
)
select #varableTableInsertIntoCode = #varableTableInsertIntoCode + ' from #' + #objectName + 'Holder holder where not exists ( select null from ' +#tableName+ ' realTable where realTable.Name = holder.Name and realTable.IsDeleted = holder.IsDeleted ) '
select #varableTableInsertIntoCode
SELECT
tabs.TABLE_NAME,
MyColumns = STUFF
(
(
SELECT ', alias.[' + r.COLUMN_NAME + ']'
FROM INFORMATION_SCHEMA.COLUMNS AS r
WHERE r.TABLE_NAME = tabs.TABLE_NAME
ORDER BY r.ORDINAL_POSITION
FOR XML PATH(''), TYPE
).value('.[1]','nvarchar(max)'),
1,1,''
)
FROM INFORMATION_SCHEMA.TABLES AS tabs
/* Optional WHERE Clause */
WHERE
tabs.TABLE_NAME = #tableName
ORDER BY tabs.TABLE_NAME;

How to include the primary key value of the selected data base on my stored procedure?

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
;
Modify your result table definition to this :
create table ##string_locations (
table_name varchar(1000),
field_name varchar(1000),
field_value varchar(8000),
id_field_name varchar(max),
id int
)
Declare these variables
#id_field_name varchar(max),
#qry varchar(max)
Include this statement right above this comment '/* search that field for the string supplied */'
SELECT #id_field_name = (SELECT top 1 QUOTENAME(keys.COLUMN_NAME)
FROM INFORMATION_SCHEMA.KEY_COLUMN_USAGE keys
WHERE keys.TABLE_NAME =PARSENAME(#table_name, 1)
and keys.TABLE_SCHEMA = PARSENAME(#table_name, 2)
and OBJECTPROPERTY(OBJECT_ID(constraint_name), 'IsPrimaryKey') = 1)
Modify your insert statement to this :
SELECT #qry = 'select ''' + #table_name + ''',''' + #field_name + ''',''' + #field_name + ''',''' + ISNULL(#id_field_name, '') + ''',' + ISNULL(#id_field_name, 'NULL') +
' from ' + #table_name + ' (nolock) ' +
'where patindex(' + #search_string + ',' + #field_name + ') > 0';
insert into ##string_locations(table_name,
field_name,
field_value,
id_field_name,
id)
exec(
#qry /* patindex works with char & text */
)
Then modify your result display :
select * from ##string_locations;
The full code is :
/* 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 = 'Alpha';
/* create results table */
drop table ##string_locations;
create table ##string_locations (
table_name varchar(1000),
field_name varchar(1000),
field_value varchar(8000),
id_field_name varchar(max),
id int
)
;
/* special settings */
set nocount on
;
/* declare variables */
declare
#table_name varchar(1000),
#field_name varchar(1000),
#id_field_name varchar(max),
#qry varchar(max)
;
/* 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
SELECT #field_name = MIN(QUOTENAME(cols.column_name))
from INFORMATION_SCHEMA.COLUMNS cols
where
cols.table_schema = PARSENAME(#table_name, 2) and
cols.table_name = PARSENAME(#table_name, 1) and
cols.data_type in ('char', 'varchar', 'nchar', 'nvarchar', 'text', 'ntext') and
QUOTENAME(cols.column_name) > #field_name
SELECT #id_field_name = (SELECT top 1 QUOTENAME(keys.COLUMN_NAME) FROM INFORMATION_SCHEMA.KEY_COLUMN_USAGE keys
WHERE keys.TABLE_NAME =PARSENAME(#table_name, 1)
and keys.TABLE_SCHEMA = PARSENAME(#table_name, 2)
and OBJECTPROPERTY(OBJECT_ID(constraint_name), 'IsPrimaryKey') = 1)
/* search that field for the string supplied */
if #field_name is not null
begin
SELECT #qry = 'select ''' + #table_name + ''',''' + #field_name + ''',''' + #field_name + ''',''' + ISNULL(#id_field_name, 'NULL') + ''',' + ISNULL(#id_field_name, 'NULL') +
' from ' + #table_name + ' (nolock) ' +
'where patindex(' + #search_string + ',' + #field_name + ') > 0';
insert into ##string_locations(table_name, field_name, field_value, id_field_name, id)
exec(
#qry
)
end
;
end
;
end
;
select * from ##string_locations;
;
Sample Result that I want to achieve:
table_name [ProjectDescription]
field_name [dbo].[ProjectProposals]
field_value Sencha Project
ID 23

Searching a value in the whole database [duplicate]

This question already has answers here:
Find a value anywhere in a database
(18 answers)
Closed 8 years ago.
Is there a way to search for a value in the entire database without quoting each table that it might or might not be in?
For example:
select all.tables from db
where all.tables = value.x
DECLARE #SearchStr nvarchar(100)
SET #SearchStr = 'tablename'
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', '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
DROP TABLE #Results

Find a string by searching all tables in SQL Server

Is there any way to search for a string in all tables of a database in SQL Server?
I want to search for string say john. The result should show the tables and their respective row that contain john.
If you are like me and have certain restrictions in a production environment, you may wish to use a table variable instead of temp table, and an ad-hoc query rather than a create procedure.
Of course depending on your sql server instance, it must support table variables.
I also added a USE statement to narrow the search scope
USE DATABASE_NAME
DECLARE #SearchStr nvarchar(100) = 'SEARCH_TEXT'
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
A bit late but hopefully useful.
Why not try some of the third party tools that can be integrated into SSMS.
I’ve worked with ApexSQL Search (100% free) with good success for both schema and data search and there is also SSMS tools pack that has this feature (not free for SQL 2012 but quite affordable).
Stored procedure above is really great; it’s just that this is way more convenient in my opinion. Also, it would require some slight modifications if you want to search for datetime columns or GUID columns and such…
To update TechDo's answer for SQL server 2012. You need to change: 'FROM ' + #TableName + ' (NOLOCK) ' to FROM ' + #TableName + 'WITH (NOLOCK) ' +
Other wise you will get the following error: Deprecated feature 'Table hint without WITH' is not supported in this version of SQL Server.
Below is the complete updated stored procedure:
CREATE PROC SearchAllTables
(
#SearchStr nvarchar(100)
)
AS
BEGIN
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', '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 + 'WITH (NOLOCK) ' +
' WHERE ' + #ColumnName + ' LIKE ' + #SearchStr2
)
END
END
END
SELECT ColumnName, ColumnValue FROM #Results
END
A bit late, but you can easily find a string with this query
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)
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
There's no need for nested looping (outer looping through tables and inner looping through all table columns). One can retrieve all (or arbitrary selected/filtered) table-column combinations from INFORMATION_SCHEMA.COLUMNS and in one loop simply pass through (search) all of them:
DECLARE #search VARCHAR(100), #table SYSNAME, #column SYSNAME
DECLARE curTabCol CURSOR FOR
SELECT c.TABLE_SCHEMA + '.' + c.TABLE_NAME, c.COLUMN_NAME
FROM INFORMATION_SCHEMA.COLUMNS c
JOIN INFORMATION_SCHEMA.TABLES t
ON t.TABLE_NAME=c.TABLE_NAME AND t.TABLE_TYPE='BASE TABLE' -- avoid views
WHERE c.DATA_TYPE IN ('varchar','nvarchar') -- searching only in these column types
--AND c.COLUMN_NAME IN ('NAME','DESCRIPTION') -- searching only in these column names
SET #search='john'
OPEN curTabCol
FETCH NEXT FROM curTabCol INTO #table, #column
WHILE (##FETCH_STATUS = 0)
BEGIN
EXECUTE('IF EXISTS
(SELECT * FROM ' + #table + ' WHERE ' + #column + ' = ''' + #search + ''')
PRINT ''' + #table + '.' + #column + '''')
FETCH NEXT FROM curTabCol INTO #table, #column
END
CLOSE curTabCol
DEALLOCATE curTabCol
I have written a SP for the this which returns the search results in form of Table name, the Column names in which the search keyword string was found as well as the searches the corresponding rows as shown in below screen shot.
This might not be the most efficient solution but you can always modify and use it according to your need.
IF OBJECT_ID('sp_KeywordSearch', 'P') IS NOT NULL
DROP PROC sp_KeywordSearch
GO
CREATE PROCEDURE sp_KeywordSearch #KeyWord NVARCHAR(100)
AS
BEGIN
DECLARE #Result TABLE
(TableName NVARCHAR(300),
ColumnName NVARCHAR(MAX))
DECLARE #Sql NVARCHAR(MAX),
#TableName NVARCHAR(300),
#ColumnName NVARCHAR(300),
#Count INT
DECLARE #tableCursor CURSOR
SET #tableCursor = CURSOR LOCAL SCROLL FOR
SELECT N'SELECT #Count = COUNT(1) FROM [dbo].[' + T.TABLE_NAME + '] WITH (NOLOCK) WHERE CAST([' + C.COLUMN_NAME +
'] AS NVARCHAR(MAX)) LIKE ''%' + #KeyWord + N'%''',
T.TABLE_NAME,
C.COLUMN_NAME
FROM INFORMATION_SCHEMA.TABLES AS T WITH (NOLOCK)
INNER JOIN INFORMATION_SCHEMA.COLUMNS AS C WITH (NOLOCK)
ON T.TABLE_SCHEMA = C.TABLE_SCHEMA AND
T.TABLE_NAME = C.TABLE_NAME
WHERE T.TABLE_TYPE = 'BASE TABLE' AND
C.TABLE_SCHEMA = 'dbo' AND
C.DATA_TYPE NOT IN ('image', 'timestamp')
OPEN #tableCursor
FETCH NEXT FROM #tableCursor INTO #Sql, #TableName, #ColumnName
WHILE (##FETCH_STATUS = 0)
BEGIN
SET #Count = 0
EXEC sys.sp_executesql
#Sql,
N'#Count INT OUTPUT',
#Count OUTPUT
IF #Count > 0
BEGIN
INSERT INTO #Result
(TableName, ColumnName)
VALUES (#TableName, #ColumnName)
END
FETCH NEXT FROM #tableCursor INTO #Sql, #TableName, #ColumnName
END
CLOSE #tableCursor
DEALLOCATE #tableCursor
SET #tableCursor = CURSOR LOCAL SCROLL FOR
SELECT SUBSTRING(TB.Sql, 1, LEN(TB.Sql) - 3) AS Sql, TB.TableName, SUBSTRING(TB.Columns, 1, LEN(TB.Columns) - 1) AS Columns
FROM (SELECT R.TableName, (SELECT R2.ColumnName + ', ' FROM #Result AS R2 WHERE R.TableName = R2.TableName FOR XML PATH('')) AS Columns,
'SELECT * FROM ' + R.TableName + ' WITH (NOLOCK) WHERE ' +
(SELECT 'CAST(' + R2.ColumnName + ' AS NVARCHAR(MAX)) LIKE ''%' + #KeyWord + '%'' OR '
FROM #Result AS R2
WHERE R.TableName = R2.TableName
FOR
XML PATH('')) AS Sql
FROM #Result AS R
GROUP BY R.TableName) TB
ORDER BY TB.Sql
OPEN #tableCursor
FETCH NEXT FROM #tableCursor INTO #Sql, #TableName, #ColumnName
WHILE (##FETCH_STATUS = 0)
BEGIN
PRINT #Sql
SELECT #TableName AS [Table],
#ColumnName AS Columns
EXEC(#Sql)
FETCH NEXT FROM #tableCursor INTO #Sql, #TableName, #ColumnName
END
CLOSE #tableCursor
DEALLOCATE #tableCursor
END
There are lots of workable answers already. Just thought I would add one I came up with that has a lot of optional funcionality.
--=======================================================================
-- 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;
*********************************************************************/
Improving the amazing answer from #Brandon, I added type to ntext and xml using castings:
BEGIN TRAN
DECLARE #SearchStr nvarchar(100) = 'SEARCH_TEXT'
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', 'ntext', 'xml')
AND QUOTENAME(COLUMN_NAME) > #ColumnName
)
IF #ColumnName IS NOT NULL
BEGIN
INSERT INTO #Results
EXEC
(
'SELECT ''' + #TableName + '.' + #ColumnName + ''', LEFT((cast(' + #ColumnName + ' as nvarchar(max))), 3630)
FROM ' + #TableName + ' (NOLOCK) ' +
' WHERE (cast(' + #ColumnName + ' as nvarchar(max))) LIKE ' + #SearchStr2
)
END
END
END
SELECT ColumnName, ColumnValue FROM #Results
ROLLBACK
Not to take away from the excellent answer by #Brandon but the OP requested "The result should show the tables and their respective row". I created a record-level solution based on the original answer from #Brandon that also avoids the use of CURSORs used by others here by simply concatenating all the appropriate columns into one string. (I have the feeling this would perform better but I honestly haven't compared results - feel free to do so and provide feedback here.)
NB I have used the STRING_AGG function to concatenate the columns. If you have an older version of SQL Server you may need to use one of the alternate methods that can be found online.
CREATE PROC [dbo].[SearchAllTablesByRecord]
(
#SearchStr NVARCHAR(100)
)
AS
BEGIN
SET NOCOUNT ON
DECLARE #TableName NVARCHAR(256), #SearchStr2 NVARCHAR(110)
DECLARE #ColumnList NVARCHAR(2048), #ColumnJoin NVARCHAR(2048)
SET #TableName = ''
SET #SearchStr2 = QUOTENAME('%' + #SearchStr + '%','''')
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 QUOTENAME(TABLE_SCHEMA) + '.' + QUOTENAME(TABLE_NAME) > #TableName
AND OBJECTPROPERTY(
OBJECT_ID(
QUOTENAME(TABLE_SCHEMA) + '.' + QUOTENAME(TABLE_NAME)
), 'IsMSShipped'
) = 0
)
PRINT #TableName -- For progress monitoring
SET #ColumnList =
(
SELECT STRING_AGG(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')
)
SET #ColumnJoin = REPLACE(#ColumnList,',','+')
IF #ColumnList <> ''
EXEC
(
'SELECT ''' + #TableName + ''' AS [Table],' + #ColumnList + '
INTO #Results
FROM ' + #TableName + ' (NOLOCK) ' +
' WHERE ' + #ColumnJoin + ' LIKE ' + #SearchStr2 + '
IF ##ROWCOUNT > 0 SELECT * FROM #Results'
)
END
END
This was very helpful. I wanted to import this function to a Postgre SQL database. Thought i would share it with anyone who is interested. Will have them a few hours. Note: this function creates a list of SQL statements that can be copied and executed on the Postgre database. Maybe someone smarter then me can get Postgre to create and execute the statements all in one function.
CREATE OR REPLACE FUNCTION SearchAllTables(_search text) RETURNS TABLE( txt text ) as $funct$
DECLARE __COUNT int;
__SQL text;
BEGIN
EXECUTE 'SELECT COUNT(0) FROM INFORMATION_SCHEMA.COLUMNS
WHERE DATA_TYPE = ''text''
AND table_schema = ''public'' ' INTO __COUNT;
RETURN QUERY
SELECT CASE WHEN ROW_NUMBER() OVER (ORDER BY table_name) < __COUNT THEN
'SELECT ''' || table_name ||'.'|| column_name || ''' AS tbl, "' || column_name || '" AS col FROM "public"."' || "table_name" || '" WHERE "'|| "column_name" || '" ILIKE ''%' || _search || '%'' UNION ALL'
ELSE
'SELECT ''' || table_name ||'.'|| column_name || ''' AS tbl, "' || column_name || '" AS col FROM "public"."' || "table_name" || '" WHERE "'|| "column_name" || '" ILIKE ''%' || _search || '%'''
END AS txt
FROM INFORMATION_SCHEMA.COLUMNS
WHERE DATA_TYPE = 'text'
AND table_schema = 'public';
END
$funct$ LANGUAGE plpgsql;
The answer that was mentioned in this post already several times I have adopted a little bit because I needed to search in only one table too:
(and also made input for the table name a bit more simpler)
ALTER PROC dbo.db_compare_SearchAllTables_sp
(
#SearchStr nvarchar(100),
#TableName nvarchar(256) = ''
)
AS
BEGIN
if PARSENAME(#TableName, 2) is null
set #TableName = 'dbo.' + QUOTENAME(#TableName, '"')
declare #results TABLE(ColumnName nvarchar(370), ColumnValue nvarchar(3630))
SET NOCOUNT ON
DECLARE #ColumnName nvarchar(128) = '', #SearchStr2 nvarchar(110)
SET #SearchStr2 = QUOTENAME('%' + #SearchStr + '%','''')
IF #TableName <> ''
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 + ' WITH (NOLOCK) ' +
' WHERE ' + #ColumnName + ' LIKE ' + #SearchStr2
)
END
END
ELSE
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 + ' WITH (NOLOCK) ' +
' WHERE ' + #ColumnName + ' LIKE ' + #SearchStr2
)
END
END
END
SELECT ColumnName, ColumnValue FROM #results
END
[CREATE PROC SearchAllTables ( #SearchStr nvarchar(100) ) AS
BEGIN
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
EXEC SearchAllTables 'Computer'][1]
[1]: https://koukia.ca/search-for-a-string-in-all-tables-and-all-fields-of-a-database-with-tsql-b6f8a1bfda37