How to find specific word in all columns of a table - sql-server

this is my table structure and data.
create table tbl_test
(id int identity(1,1),
column1 nvarchar(50),
coulmn2 nvarchar(50),
coulmn3 nvarchar(50))-- Create a table
insert into tbl_Test (column1,coulmn2,coulmn3) values
('qqGriffrr','Serjey','Maciej')
insert into tbl_Test (column1,coulmn2,coulmn3) values('King','Fisher','Ajay')
insert into tbl_Test (column1,coulmn2,coulmn3) values('Paul','ssGriffdd','Serjey')
insert into tbl_Test (column1,coulmn2,coulmn3) values('King','Fisher','xxGriffzzz')
this way i am finding and it is working
select * from tbl_test where 'Griff'
IN(column1 ,column2 ,column3)
select * from tbl_test where column1 like '%Griff%'
OR coulmn2 like '%Griff%'
OR coulmn3 like '%Griff%'
i am looking some neat way hence i do not have to include so many OR and Like clause if no of column would increase. so tell me the best approach to solve it.
thanks

If you have an ability to use full text search you can just do it like this:
select *
from test_table
where CONTAINS(*, '"blablabla"')

A little more generic, remove the external loop if you need only a single table:
DECLARE #TableName sysname, #ColName sysname
DECLARE #Find sysname
DECLARE #sql nvarchar(4000)
SET #Find = N'sometext'
DECLARE cTables CURSOR FOR SELECT name from dbo.sysobjects where Category = 0 AND type NOT IN (N'F', N'FN', N'IF', N'TF', N'P', N'TR', N'V', N'K')
OPEN cTables
FETCH NEXT FROM cTables INTO #TableName
WHILE ##FETCH_STATUS = 0
BEGIN
DECLARE cColumns CURSOR FOR SELECT column_name FROM information_schema.columns WHERE table_name = #TableName AND DATA_TYPE NOT IN ('Image', 'bit', 'int', 'datetime', 'ntext', 'varbinary')
OPEN cColumns
FETCH NEXT FROM cColumns INTO #ColName
WHILE ##FETCH_STATUS = 0
BEGIN
SET #sql = N'SET NOCOUNT ON
DECLARE #Value sysname, #NewValue sysname
IF EXISTS (SELECT 1 FROM [' + #TableName + N'] WHERE [' + #ColName + N'] LIKE N''%'+ #Find + '%'')
BEGIN
SELECT #Value = [' + #ColName + N'] FROM [' + #TableName + N'] WHERE [' + #ColName + N'] LIKE N''%' + #Find + '%''
SELECT ''' + #ColName + N''' [Column], ''' + #TableName + N''' [Table], [' + #ColName + N'] [ValueFound], * FROM [' + #TableName + N'] WHERE [' + #ColName + N'] LIKE N''%' + #Find + '%''
END
'
-- PRINT #sql
EXEC sp_sqlexec #sql
FETCH NEXT FROM cColumns INTO #ColName
END
CLOSE cColumns;
DEALLOCATE cColumns;
FETCH NEXT FROM cTables INTO #TableName
END
CLOSE cTables;
DEALLOCATE cTables;
edited to use only selected table:
DECLARE #ColName sysname
DECLARE #Find sysname
DECLARE #sql nvarchar(4000), #TableName sysname
SET #Find = N'sometext'
SET #TableName = N'YourTable'
DECLARE cColumns CURSOR FOR SELECT column_name FROM information_schema.columns WHERE table_name = #TableName AND DATA_TYPE NOT IN ('Image', 'bit', 'int', 'datetime', 'ntext', 'varbinary')
OPEN cColumns
FETCH NEXT FROM cColumns INTO #ColName
WHILE ##FETCH_STATUS = 0
BEGIN
SET #sql = N'SET NOCOUNT ON
DECLARE #Value sysname, #NewValue sysname
IF EXISTS (SELECT 1 FROM [' + #TableName + N'] WHERE [' + #ColName + N'] LIKE N''%'+ #Find + '%'')
BEGIN
SELECT #Value = [' + #ColName + N'] FROM [' + #TableName + N'] WHERE [' + #ColName + N'] LIKE N''%' + #Find + '%''
SELECT ''' + #ColName + N''' [Column], ''' + #TableName + N''' [Table], [' + #ColName + N'] [ValueFound], * FROM [' + #TableName + N'] WHERE [' + #ColName + N'] LIKE N''%' + #Find + '%''
END
'
-- PRINT #sql
EXEC sp_sqlexec #sql
FETCH NEXT FROM cColumns INTO #ColName
END
CLOSE cColumns;
DEALLOCATE cColumns;

select *
from tbl_test
where column1+column2 +column3 like '%Griff%'

I found one which looks good. here it is.
Searching and finding a string value in all columns in a SQL Server table
CREATE PROCEDURE sp_FindStringInTable #stringToFind VARCHAR(100), #schema sysname, #table sysname
AS
DECLARE #sqlCommand VARCHAR(8000)
DECLARE #where VARCHAR(8000)
DECLARE #columnName sysname
DECLARE #cursor VARCHAR(8000)
BEGIN TRY
SET #sqlCommand = 'SELECT * FROM [' + #schema + '].[' + #table + '] WHERE'
SET #where = ''
SET #cursor = 'DECLARE col_cursor CURSOR FOR SELECT COLUMN_NAME
FROM ' + DB_NAME() + '.INFORMATION_SCHEMA.COLUMNS
WHERE TABLE_SCHEMA = ''' + #schema + '''
AND TABLE_NAME = ''' + #table + '''
AND DATA_TYPE IN (''char'',''nchar'',''ntext'',''nvarchar'',''text'',''varchar'')'
EXEC (#cursor)
OPEN col_cursor
FETCH NEXT FROM col_cursor INTO #columnName
WHILE ##FETCH_STATUS = 0
BEGIN
IF #where <> ''
SET #where = #where + ' OR'
SET #where = #where + ' [' + #columnName + '] LIKE ''' + #stringToFind + ''''
FETCH NEXT FROM col_cursor INTO #columnName
END
CLOSE col_cursor
DEALLOCATE col_cursor
SET #sqlCommand = #sqlCommand + #where
--PRINT #sqlCommand
EXEC (#sqlCommand)
END TRY
BEGIN CATCH
PRINT 'There was an error. Check to make sure object exists.'
IF CURSOR_STATUS('variable', 'col_cursor') <> -3
BEGIN
CLOSE col_cursor
DEALLOCATE col_cursor
END
END CATCH
Calling this way
EXEC sp_FindStringInTable 'Irv%', 'Person', 'Address'

Related

How to change existing triggers to be with 'not for replication' in merge replication in SQL Server?

How to make a script that will change all triggers in a database to be NOT FOR REPLICATION? Is there a system procedure for it or we need to parse its definition and inject NOT FOR REPLICATION?
Yes, manually, but first I would try this way:
proc [dbo].[db_compare_make_trigger_NOT_FOR_REPLICATION_sp]
as
declare cur cursor fast_forward for
select st.name, definition, is_disabled, OBJECT_NAME(parent_id)
from sys.triggers st join
sys.sql_modules sm on st.object_id = sm.object_id
where is_ms_shipped = 0
and is_not_for_replication = 0
and parent_id > 0
declare #name nvarchar(127), #definition nvarchar(max), #is_disabled bit, #table nvarchar(127)
open cur
fetch next from cur into #name, #definition, #is_disabled, #table
while ##FETCH_STATUS = 0
begin
declare #sql nvarchar(max) = null
declare #name_bckp nvarchar(127) = '__' + #name + N'_' + replace(replace(replace(replace(CONVERT(nvarchar,getdate(), 126), '-', '_'), ':', '_'), '.', '_'), 'T', '_')
PRINT #NAME + ' ON ' + #table
set #sql = dbo.RegExReplace(#definition, 'AS\s+BEGIN', ' NOT FOR REPLICATION' + CHAR(13) + CHAR(10) + 'AS' + CHAR(13) + CHAR(10) + 'BEGIN')
if charindex('NOT FOR REPLICATION', #sql) = 0
set #sql = dbo.RegExReplace(#definition, 'AS\s+SET NOCOUNT ON', ' NOT FOR REPLICATION' + CHAR(13) + CHAR(10) + 'AS' + CHAR(13) + CHAR(10) + 'SET NOCOUNT ON')
if charindex('NOT FOR REPLICATION', #sql) > 0
begin try
--BCKP it
exec sys.sp_rename #NAME, #name_bckp
set #definition = 'DISABLE TRIGGER [' + #name_bckp + '] ON [' + #table + ']'
execute sp_executesql #definition
--create it
execute sp_executesql #sql
--set previous state
if #is_disabled = 1
set #definition = 'DISABLE TRIGGER [' + #NAME + '] ON [' + #table + ']'
else
set #definition = 'ENABLE TRIGGER [' + #NAME + '] ON [' + #table + ']'
execute sp_executesql #definition
set #definition = 'DROP TRIGGER [' + #name_bckp + ']'
execute sp_executesql #definition
print 'DONE!'
end try
begin catch
declare #msg nvarchar(4000) = ERROR_MESSAGE()
declare #esv int = error_severity()
declare #est int = error_state()
declare #lin int = error_line()
insert into db_log (dateCreated, msg, Level, State, Line, additional)
values(getdate(), #msg, #esv, #est, #lin, #NAME)
print 'ERROR check db_log: ' + #msg
end catch
fetch next from cur into #name, #definition, #is_disabled, #table
end
close cur
deallocate cur
And remained triggers I would do manually.
for this to work you will need:
CLR Assembly RegEx Functions for SQL Server

SQL Syntax Error in print functions using dynamic variables

When I run the below query, It does print the statements but throws the following error:
Process failed: Incorrect syntax near ')'
Code:
IF EXISTS(SELECT 1 FROM INFORMATION_SCHEMA.TABLES
WHERE TABLE_SCHEMA = 'dbo' AND TABLE_NAME = 'Table_1')
DELETE [dbo].[Table_1]
WHERE [UPDATED_DATE] <= DATEADD(dd, -90,'2018.02.23')
UPDATE DBO.T_REF_MASTER
SET LAST_PURGE_DATE = GETDATE()
WHERE TABLE_NAME = 'Table_1'
Can someone explain why is it throwing that error because when I run the individual statements one by one, it executes perfectly
--Query
DECLARE #SQL VARCHAR(MAX)
DECLARE #S VARCHAR(MAX)
DECLARE #SQLExist VARCHAR(MAX)
DECLARE #db VARCHAR(10) = 'dbo'
DECLARE #TABLE_NAME VARCHAR(200) = 'Table_1'
DECLARE #NO_OF_DAYS VARCHAR(10) = '90'
DECLARE #LAST_PURGE_DATE VARCHAR(50) = '2018-02-22 10:46:49.953'
SET #SQLExist = 'IF EXISTS((SELECT 1 FROM
INFORMATION_SCHEMA.TABLES WHERE TABLE_SCHEMA = '''
+ #db + ''' AND TABLE_NAME = ''' + #TABLE_NAME +
''')'
--PRINT #SQLExist
SET #SQL = 'DELETE [' + #db + '].[' + #TABLE_NAME
+ '] where [UPDATED_DATE] <= DATEADD(dd, -'
+ CONVERT(VARCHAR,#NO_OF_DAYS) + ',''' +
+ CONVERT(VARCHAR,#LAST_PURGE_DATE, 102) + ''')'
--PRINT #SQL
SET #S = 'UPDATE DBO.T_REF_MASTER SET LAST_PURGE_DATE =
getdate() WHERE TABLE_NAME = '
+ '''' + CONVERT(VARCHAR, #TABLE_NAME) + ''');'
PRINT #SQLExist
print #SQL
PRINT #S
I see two opening parentheses - (( - after EXISTS, but only one closing after #TABLE_NAME.
Okay agreed George. I removed those parentheses. Here's the new query:
--Query
DECLARE #SQL VARCHAR(MAX)
DECLARE #S VARCHAR(MAX)
DECLARE #SQLExist VARCHAR(MAX)
DECLARE #db VARCHAR(10) = 'dbo'
DECLARE #TABLE_NAME VARCHAR(200) = 'Table_1'
DECLARE #NO_OF_DAYS VARCHAR(10) = '90'
DECLARE #LAST_PURGE_DATE VARCHAR(50) = '2018-02-22 10:46:49.953'
SET #SQLExist = 'IF EXISTS(SELECT 1 FROM
INFORMATION_SCHEMA.TABLES WHERE TABLE_SCHEMA = '''
+ #db + ''' AND TABLE_NAME = ''' + #TABLE_NAME +
''')'
--PRINT #SQLExist
SET #SQL = 'DELETE [' + #db + '].[' + #TABLE_NAME
+ '] where [UPDATED_DATE] <= DATEADD(dd, -'
+ CONVERT(VARCHAR,#NO_OF_DAYS) + ',''' +
+ CONVERT(VARCHAR,#LAST_PURGE_DATE, 102) + ''')'
--PRINT #SQL
SET #S = 'UPDATE DBO.T_REF_MASTER SET LAST_PURGE_DATE =
getdate() WHERE TABLE_NAME = '
+ '''' + CONVERT(VARCHAR, #TABLE_NAME) + ''''
PRINT #SQLExist
print #SQL
PRINT #S
Its still spitting out the SYNTAX ERROR NEAR ')'

SQL Server : EXECUTE error when trying to query with variable statements

The task is to scroll through all tables and columns to find the table and column names containig the searched value. The script I use is:
IF Object_id('tempdb..#temp_sar') IS NOT NULL
DROP TABLE #temp_sar
go
CREATE TABLE #temp_table
(
[table_name] VARCHAR,
[column_name] VARCHAR
)
DECLARE #Table_Name VARCHAR
DECLARE #Column_Name VARCHAR
DECLARE #Search_Value UNIQUEIDENTIFIER = CONVERT(UNIQUEIDENTIFIER, '303D9191-E201-4299-809E-FC7B0213F73C')
DECLARE #CURSOR CURSOR
SET #CURSOR = CURSOR scroll FOR
(SELECT s.table_name,
s.column_name
FROM information_schema.columns s
WHERE s.data_type = 'uniqueidentifier')
OPEN #CURSOR
FETCH next FROM #CURSOR INTO #Table_Name, #Column_Name
WHILE ##FETCH_STATUS = 0
BEGIN
IF #Search_Value = EXEC ('select distinct' + #Column_Name + 'from'
+ #Table_Name + 'where' + #Column_Name + '='
+ #Search_Value)
INSERT INTO #temp_table ([table_name], [column_name])
VALUES (#Table_Name, #Column_Name)
FETCH next FROM #CURSOR INTO #Table_Name, #Column_Name
END
CLOSE #CURSOR
SELECT * FROM #temp_table;
When this is executed, I get an error:
Incorrect syntax near the keyword 'EXEC'
Please help me make this code work
There are a few problems with this line...
IF #Search_Value = Exec('select distinct' + #Column_Name + 'from'
+ #Table_Name + 'where' + #Column_Name + '='
+ #Search_Value)
First, make sure that you have spaces in the necessary places in your sql string...
Exec('select distinct ' + #Column_Name + ' from '
+ #Table_Name + ' where ' + #Column_Name + ' = '
+ #Search_Value
)
Next, if you execute a SELECT statement, the results are a data-set, not a scalar. This also means that the data-set is also not returned in the same as a function returns a scalar result.
It is possible to use EXEC #myReturn = spSomethingOrAnother(#param, #anotherParam); to capture anything sent back with a RETURN statement (At the end of the SP), but I don't think that works with Dynamic SQL...
https://learn.microsoft.com/en-us/sql/t-sql/language-elements/execute-transact-sql
Your next option could be to create a table to insert the results in to, then check that table...
INSERT INTO #TABLE EXEC #query with SQL Server 2000
CREATE TABLE #result (search_value UNIQUEIDENTIFIER)
INSERT INTO
#result (
search_value
)
EXEC(
'select distinct ' + #Column_Name + ' from '
+ #Table_Name + ' where ' + #Column_Name + ' = '
+ #Search_Value
)
IF EXISTS (SELECT * FROM #result WHERE search_value = #search_value)
...
{USE PROD
GO
IF OBJECT_ID('tempdb..#source_table') IS NOT NULL DROP TABLE #source_table
GO
IF OBJECT_ID('tempdb..#result_table') IS NOT NULL DROP TABLE #result_table
GO
CREATE TABLE #result_table (Table_Name nvarchar(max),Column_Name nvarchar(max),Searched_Value uniqueidentifier)
DECLARE #CURSOR CURSOR
DECLARE #Table_Name nvarchar(max)
DECLARE #Column_Name nvarchar(max)
DECLARE #Search_Value nvarchar(max) = concat('''','ABBDFFEA-4576-4AA9-854E-A016433C54F0','''')
SET #CURSOR = CURSOR SCROLL
FOR
(
select s.TABLE_NAME, s.COLUMN_NAME
from INFORMATION_SCHEMA.COLUMNS s
where s.DATA_TYPE = 'uniqueidentifier'
)
OPEN #CURSOR
FETCH NEXT FROM #CURSOR INTO #Table_Name, #Column_Name
WHILE ##FETCH_STATUS = 0
BEGIN
INSERT INTO #result_table (Table_Name, Column_Name, Searched_Value) EXEC('select distinct ' + ''''+ #Table_Name + '''' + ' AS Table_Name , ' + ''''+ #Column_Name + '''' + ' AS Column_Name , ' + '[' + #Column_Name + ']' + ' from ' + '[' + #Table_Name + ']' + ' where ' + '[' + #Column_Name + ']' + ' = ' + #Search_Value)
FETCH NEXT FROM #CURSOR INTO #Table_Name, #Column_Name
END
CLOSE #CURSOR
--results
SELECT * FROM #result_table}

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.

SP_Execute not returning value in output parameter

As we can see in the code below I am fetching records from comma separated values into a cursor. I have table name in the #tableName variable .
Result expected from the code below is in #ColumnName it must have comma-separated column name as a result.
DECLARE Cur CURSOR FOR
SELECT
[Value] AS TableName
FROM
[dbo].[SplitCSVs]('agency_event,agency_event_history,app_display,bulk_load_status,call_info,common_event,common_event_call,common_event_call_history,common_event_history,evcom,facility_recommendation,loi_data,loi_search,messa,message_dest,mr_pending_push_messages,scheduled_hist,sys_hist,un_hi,un_hi_child_change,un_hi_device_loc,un_hi_persl,unit_wkload,ushis')
DECLARE #Date AS VARCHAR(15);
DECLARE #Sql AS NVARCHAR(MAX);
SET #Date= '%20180414%';
DECLARE #ColumnName VARCHAR(2000);
DECLARE #tableName VARCHAR(200);
DECLARE #TValue VARCHAR(200);
SET #ColumnName = NULL;
OPEN Cur
FETCH NEXT FROM cur INTO #tableName;
--Set #tableName=N'app_access'
WHILE ##FETCH_STATUS = 0
BEGIN
PRINT 'Table Name : ' + #tableName
--print ' Before trim '+ Convert( Varchar,Len(#tableName))
SET #tableName = Replace(#tableName,CHAR(0),'');
--Horizontal Tab
SET #tableName = Replace(#tableName,CHAR(9),'');
--Line Feed
SET #tableName = Replace(#tableName,CHAR(10),'');
--Vertical Tab
SET #tableName = Replace(#tableName,CHAR(11),'');
--Form Feed
SET #tableName = Replace(#tableName,CHAR(12),'');
--Carriage Return
SET #tableName = Replace(#tableName,CHAR(13),'');
--Column Break
SET #tableName = Replace(#tableName,CHAR(14),'');
--Non-breaking space
SET #tableName = Replace(#tableName,CHAR(160),'');
SET #tableName = LTRIM(RTRIM(#tableName));
--print 'Table Name : ' + #tableName
--print ' After trim '+ Convert( Varchar,Len(ltrim( rtrim(#tableName))))
SET #Sql = null;
SET #ColumnName = Null;
--print char(39)+ Convert(varchar,#tableName) + char(39)
SET #TValue=char(39)+ Convert(varchar,#tableName) + char(39)
PRINT Tvalue :' + #TValue
--Select #ColumnName = Coalesce( #ColumnName + ',','') + COLUMN_NAME From [RAJDB_LIVE].INFORMATION_SCHEMA.COLUMNS where TABLE_NAME = #TValue
SET #Sql ='Select #ColumnName = Coalesce( #ColumnName + '','','''') + COLUMN_NAME From [RAJDB_LIVE].INFORMATION_SCHEMA.COLUMNS where TABLE_NAME = #TbValue '
PRINT 'Sql Query ' + #Sql
EXECUTE sp_executesql #Sql, N'#TbValue VARCHAR(100),#ColumnName Varchar(2000) OUTPUT', #TbValue= #TValue, #ColumnName= #ColumnName Out;
--print 'Sql Query ' + #Sql
--EXEC sp_executesql #Sql
--select #ColumnName=[Value] FROM [dbo].[GetColumnName](#TValue)
--Set #Sql ='Select ' + #ColumnName + ' = Coalesce(' + #ColumnName + ' + '','','''') + COLUMN_NAME From [KOTADB_ARCH].INFORMATION_SCHEMA.COLUMNS where TABLE_NAME=' + #TValue
--print 'Sql Query ' + #Sql
PRINT 'Column Statement : ' + #ColumnName;
BREAK
--exec sp_Executesql #Sql
FETCH NEXT FROM cur INTO #tableName
END
CLOSE cur
DEALLOCATE Cur

Resources