Just wondering any one can help me with this T-SQL script, error code below. As my expertise in SQL is very limited I am not sure if this means that store procedure is missing or something actually wrong with the script.
EXEC isp_ALTER_INDEX
#dbName = 'MODEV',
#statsMode = 'SAMPLED',
#defragType = 'REBUILD',
#minFragPercent = 5,
#maxFragPercent = 100,
#minRowCount = 1000000,
#logHistory = 1,
#sortInTempdb = 1
Error
Executed as user: Could not find stored procedure 'isp_ALTER_INDEX'. [SQLSTATE 42000] (Error 2812). The step failed.
you should first create the procedure before calling it, by below code:
CREATE PROC [dbo].[isp_ALTER_INDEX]
(
#dbName sysname,
#statsMode varchar(8) = 'SAMPLED',
#defragType varchar(10) = 'REORGANIZE',
#minFragPercent int = 25,
#maxFragPercent int = 100,
#minRowCount int = 0
)
AS
SET NOCOUNT ON
IF #statsMode NOT IN ('LIMITED', 'SAMPLED', 'DETAILED')
BEGIN
RAISERROR('#statsMode must be LIMITED, SAMPLED or DETAILED', 16, 1)
RETURN
END
IF #defragType NOT IN ('REORGANIZE', 'REBUILD')
BEGIN
RAISERROR('#defragType must be REORGANIZE or REBUILD', 16, 1)
RETURN
END
DECLARE
#i int, #objectId int, #objectName sysname, #indexId int, #indexName sysname,
#schemaName sysname, #partitionNumber int, #partitionCount int,
#sql nvarchar(4000), #edition int, #parmDef nvarchar(500), #allocUnitType nvarchar(60),
#indexType nvarchar(60), #online bit, #disabled bit, #dataType nvarchar(128),
#charMaxLen int
SELECT #edition = CONVERT(int, SERVERPROPERTY('EngineEdition'))
SELECT
IDENTITY(int, 1, 1) AS FragIndexId,
[object_id] AS ObjectId,
index_id AS IndexId,
avg_fragmentation_in_percent AS FragPercent,
record_count AS RecordCount,
partition_number AS PartitionNumber,
index_type_desc AS IndexType,
alloc_unit_type_desc AS AllocUnitType,
0 AS Online
INTO #FragIndex
FROM sys.dm_db_index_physical_stats (DB_ID(#dbName), NULL, NULL, NULL, #statsMode)
WHERE
avg_fragmentation_in_percent > #minFragPercent AND
avg_fragmentation_in_percent < #maxFragPercent AND
index_id > 0
ORDER BY ObjectId
-- LIMITED does not include data for record_count
IF #statsMode IN ('SAMPLED', 'DETAILED')
DELETE FROM #FragIndex
WHERE RecordCount < #minRowCount
-- Developer and Enterprise have the ONLINE = ON option for REBUILD
-- Indexes, including indexes on global temp tables, can be rebuilt online with the following exceptions:
-- Disabled indexes, XML indexes, Indexes on local temp tables, Partitioned indexes,
-- Clustered indexes if the underlying table contains LOB data types,
-- Nonclustered indexes that are defined with LOB data type columns
IF #defragType = 'REBUILD' AND #edition = 3
BEGIN
UPDATE #FragIndex
SET Online = 1
UPDATE #FragIndex
SET Online =
CASE
WHEN IndexType = 'XML INDEX' THEN 0
WHEN IndexType = 'NONCLUSTERED INDEX' AND AllocUnitType = 'LOB_DATA' THEN 0
ELSE 1
END
-- we can't determine if the indexes are disabled or partitioned yet,
-- so we'll need to figure that out during the loop
-- we also have to figure out if the table contains lob_data when
-- a clustered index exists during the loop
END
SELECT #i = MIN(FragIndexId)
FROM #FragIndex
SELECT
#objectId = ObjectId,
#indexId = IndexId,
#partitionNumber = PartitionNumber,
#indexType = IndexType,
#online = Online
FROM #FragIndex
WHERE FragIndexId = #i
WHILE ##ROWCOUNT <> 0
BEGIN
SET #sql = '
SELECT #objectName = o.[name], #schemaName = s.[name]
FROM ' + #dbName + '.sys.objects o
JOIN ' + #dbName + '.sys.schemas s
ON s.schema_id = o.schema_id
WHERE o.[object_id] = #objectId'
SET #parmDef = N'#objectId int, #objectName sysname OUTPUT, #schemaName sysname OUTPUT'
EXEC sp_executesql
#sql, #parmDef, #objectId = #objectId,
#objectName = #objectName OUTPUT, #schemaName = #schemaName OUTPUT
IF #indexType = 'CLUSTERED INDEX'
BEGIN
-- can't use online option if index is clustered and table contains following
-- data types: text, ntext, image, varchar(max), nvarchar(max), varbinary(max) or xml
-- CHARACTER_MAXIMUM_LENGTH column will equal -1 for max size or xml
SET #sql = '
SELECT #online = 0
FROM ' + #dbName + '.INFORMATION_SCHEMA.COLUMNS c
WHERE TABLE_NAME = #objectName AND
(DATA_TYPE IN (''text'', ''ntext'', ''image'') OR
CHARACTER_MAXIMUM_LENGTH = -1)'
SET #parmDef = N'#objectName sysname, #online bit OUTPUT'
EXEC sp_executesql
#sql, #parmDef, #objectName = #objectName, #online = #online OUTPUT
END
SET #sql = '
SELECT #indexName = [name], #disabled = is_disabled
FROM ' + #dbName + '.sys.indexes
WHERE [object_id] = #objectId AND index_id = #indexId'
SET #parmDef = N'
#objectId int, #indexId int, #indexName sysname OUTPUT, #disabled bit OUTPUT'
EXEC sp_executesql
#sql, #parmDef, #objectId = #objectId, #indexId = #indexId,
#indexName = #indexName OUTPUT, #disabled = #disabled OUTPUT
SET #sql = '
SELECT #partitionCount = COUNT(*)
FROM ' + #dbName + '.sys.partitions
WHERE [object_id] = #objectId AND index_id = #indexId'
SET #parmDef = N'#objectId int, #indexId int, #partitionCount int OUTPUT'
EXEC sp_executesql
#sql, #parmDef, #objectId = #objectId, #indexId = #indexId,
#partitionCount = #partitionCount OUTPUT
SET #sql = 'ALTER INDEX [' + #indexName + '] ON [' + #dbName + '].[' +
#schemaName + '].[' + #objectName + '] ' + #defragType
IF #online = 1 AND #disabled = 0 AND #partitionCount = 1
SET #sql = #sql + ' WITH (ONLINE = ON)'
IF #partitionCount > 1 AND #disabled = 0 AND #indexType <> 'XML INDEX'
SET #sql = #sql + ' PARTITION = ' + CAST(#partitionNumber AS varchar(10))
EXEC (#SQL)
SELECT #i = MIN(FragIndexId)
FROM #FragIndex
WHERE FragIndexId > #i
SELECT
#objectId = ObjectId,
#indexId = IndexId,
#partitionNumber = PartitionNumber,
#indexType = IndexType,
#online = Online
FROM #FragIndex
WHERE FragIndexId = #i
END
DROP TABLE #FragIndex
Related
I would like to create a temptable that will hold the result of this query:
set #sql = 'use ' + #dbname + '; select db_name() , name from sys.tables where is_ms_shipped = 0 and type_desc = ''USER_TABLE'' '
exec (#sql)
Here is the full query I have:
declare #minx int = 0
declare #maxx int = (select max(id) from #DBS)
declare #sql nvarchar(1000)
declare #dbname varchar (130)
declare #count int
Select *
from #DBS
while (#count is not null
and #count <= #maxx)
begin
select #dbname = dbname
from #DBS where id = #count
print 'id = ' + convert (varchar, #count) + ' dbname = ' + #dbname
set #sql = 'use ' + #dbname + '; select db_name() , name from sys.tables where is_ms_shipped = 0 and type_desc = ''USER_TABLE'' '
exec (#sql)
set #count = #count + 1
break
end;
I have tried so many things and always getting error messages.
Anybody could give me an insight?
Not sure how you populate #DBS but:
CREATE TABLE #tables(db sysname, table_name sysname);
DECLARE #dbs cursor,
#context nvarchar(1000),
#sql nvarchar(max);
SET #sql = N'INSERT #tables(db, table_name)
SELECT DB_NAME(), name
FROM sys.tables
WHERE type = ''U'' AND is_ms_shipped = 0;';
SET #dbs = CURSOR FOR SELECT QUOTENAME(dbname)
+ N'.sys.sp_executesql' FROM #DBS;
OPEN #dbs;
FETCH NEXT FROM #dbs INTO #context;
WHILE ##FETCH_STATUS = 0
BEGIN
EXECUTE #context #sql;
FETCH NEXT FROM #dbs INTO #context;
END
SELECT db, table_name FROM #tables;
Also see this related question.
The stored procedure used for analyzing the fragmentation percentage takes more than 4 to 5 hrs to execute. I'm not much expert in writing and analyzing queries. Any help/suggestions to get this executed fast would be much appreciated. There is a job created to run this stored procedure , and the job duration is more than 4 to 5 hrs every day.
CREATE PROCEDURE [dbo].[Fragmentation_Analysis]
AS
BEGIN
SET NOCOUNT ON;
DECLARE #Dbid Int, #Objectid Int, #Indexid Int,
#Partitioncount Bigint, #Schemaname Sysname,
#Objectname Sysname
DECLARE #Indexname Sysname, #Partitionnum Bigint,
#Partitions Bigint, #Frag Float, #DefragCount Int
DECLARE #Qry Varchar(Max)
SET #Dbid = Db_Id()
SET #Qry = ''
IF (SELECT Object_Id('Tempdb..#FragTabInfo')) IS NOT NULL
DROP TABLE #FragTabInfo
CREATE TABLE #FragTabInfo
(
Objectid Int,
Indexid Int,
Partitionnum Int,
Frag Float
)
SET #Qry = 'INSERT INTO #FragTabInfo (Objectid, Indexid, Partitionnum, Frag)
SELECT
Object_Id AS Objectid,
Index_Id AS Indexid,
Partition_Number AS Partitionnum,
Avg_Fragmentation_In_Percent AS Frag
FROM
Sys.Dm_Db_Index_Physical_Stats (' + Convert(Varchar(9),#Dbid) + ', Null, Null , Null, ''Limited'')
WHERE Avg_Fragmentation_In_Percent > 10.0
AND Index_Id > 0'
EXEC (#Qry)
SELECT #DefragCount = COUNT(*) FROM #FragTabInfo
IF (#DefragCount IS NULL OR #DefragCount = 0)
PRINT 'Fragmentation% is <= 10.0 for all tables'
DECLARE Partitions CURSOR FOR
SELECT *
FROM #FragTabInfo
ORDER BY Object_Name(Objectid)
OPEN Partitions
FETCH NEXT FROM Partitions INTO #Objectid, #Indexid, #Partitionnum, #Frag
WHILE ##Fetch_Status = 0
BEGIN
SELECT #Objectname = O.Name, #Schemaname = S.Name
FROM Sys.Objects AS O
JOIN Sys.Schemas AS S ON S.Schema_Id = O.Schema_Id
WHERE O.Object_Id = #Objectid
SELECT #Indexname = Name
FROM Sys.Indexes
WHERE Object_Id = #Objectid AND Index_Id = #Indexid
SELECT #Partitioncount = COUNT(*)
FROM Sys.Partitions
WHERE Object_Id = #Objectid AND Index_Id = #Indexid
-- 30 Is An Arbitrary Decision Point At Which To Switch Between Reorganizing And Rebuilding
IF #Frag < 30.0
BEGIN
SELECT #Qry = 'ALTER INDEX ' + #Indexname + ' ON ' + #Schemaname + '.' + #Objectname + ' REORGANIZE'
EXEC(#Qry)
END
IF #Frag >= 30.0
BEGIN
SELECT #Qry = 'ALTER INDEX ' + #Indexname +' ON ' + #Schemaname + '.' + #Objectname + ' REBUILD'
EXEC (#Qry)
END
PRINT 'Executed ' + #Qry + ' with fragmentation %' + Convert(Varchar(9),#Frag)
IF #Qry != ''
IF CharIndex('Reorganize', #Qry) = 0
BEGIN
SET #Qry = 'UPDATE STATISTICS ' + #Objectname + ' WITH SAMPLE 30 ROWS'
PRINT #Qry
EXEC (#Qry)
END
FETCH NEXT FROM Partitions INTO #Objectid, #Indexid, #Partitionnum, #Frag
END
CLOSE Partitions
DEALLOCATE Partitions
IF (SELECT Object_Id('Tempdb..#FragTabInfo')) IS NOT NULL
DROP TABLE #FragTabInfo
END
I want to write SP to delete rows from given table based on ID column. I tried the following:
CREATE PROCEDURE dbo.delResTab #schema VARCHAR(20), #table VARCHAR(50), #tableID int
AS
DECLARE #column VARCHAR(50) = (
SELECT COLUMN_NAME
FROM INFORMATION_SCHEMA.columns
WHERE TABLE_SCHEMA = #schema
AND TABLE_NAME = #table
AND ORDINAL_POSITION = 1
)
DELETE FROM #schema + '.' + #table WHERE #column >= #tableId
but this does not work obviously. Any advice?
I want to be able to run
exec dbo.delResTab #schema = 'dbo', #table = 'test', #tableID = 3
CREATE PROCEDURE dbo.delResTab
(
#schema SYSNAME,
#table SYSNAME,
#tableID INT
)
AS BEGIN
SET NOCOUNT ON;
DECLARE #SQL NVARCHAR(MAX)
SELECT #SQL = '
DELETE FROM [' + #schema + '].[' + #table + ']
WHERE ' + c.name + ' >= ' + CAST(#tableID AS NVARCHAR(10))
FROM sys.columns c
WHERE c.is_identity = 1
AND c.[object_id] = OBJECT_ID(#schema + '.' + #table)
--PRINT #SQL
EXEC sys.sp_executesql #SQL
END
In T-SQL is it possible to give me a list of tables and columns that contain specified column value?
For example, I get a employee report generated out of a SQL Server database that shows "John" as name in one of the columns. Now I want to find out where "John" appears as a field value in any table/column in the database.
So in English my query should sound like;
Select table, column
from database A
where field = 'John'
Thanks
Try with this procedure
CREATE PROCEDURE FindMyData_String #DataToFind NVARCHAR(4000),
#ExactMatch BIT = 0
AS
SET NOCOUNT ON
DECLARE #Temp TABLE
(
RowId INT IDENTITY(1, 1),
SchemaName SYSNAME,
TableName SYSNAME,
ColumnName SYSNAME,
DataType VARCHAR(100),
DataFound BIT
)
INSERT INTO #Temp
(TableName,
SchemaName,
ColumnName,
DataType)
SELECT C.Table_Name,
C.TABLE_SCHEMA,
C.Column_Name,
C.Data_Type
FROM Information_Schema.Columns AS C
INNER JOIN Information_Schema.Tables AS T
ON C.Table_Name = T.Table_Name
AND C.TABLE_SCHEMA = T.TABLE_SCHEMA
WHERE Table_Type = 'Base Table'
AND Data_Type IN ( 'ntext', 'text', 'nvarchar', 'nchar',
'varchar', 'char' )
DECLARE #i INT
DECLARE #MAX INT
DECLARE #TableName SYSNAME
DECLARE #ColumnName SYSNAME
DECLARE #SchemaName SYSNAME
DECLARE #SQL NVARCHAR(4000)
DECLARE #PARAMETERS NVARCHAR(4000)
DECLARE #DataExists BIT
DECLARE #SQLTemplate NVARCHAR(4000)
SELECT #SQLTemplate = CASE
WHEN #ExactMatch = 1 THEN 'If Exists(Select *
From ReplaceTableName
Where Convert(nVarChar(4000), [ReplaceColumnName])
= '''
+ #DataToFind
+ '''
)
Set #DataExists = 1
Else
Set #DataExists = 0'
ELSE 'If Exists(Select *
From ReplaceTableName
Where Convert(nVarChar(4000), [ReplaceColumnName])
Like ''%'
+ #DataToFind
+ '%''
)
Set #DataExists = 1
Else
Set #DataExists = 0'
END,
#PARAMETERS = '#DataExists Bit OUTPUT',
#i = 1
SELECT #i = 1,
#MAX = MAX(RowId)
FROM #Temp
WHILE #i <= #MAX
BEGIN
SELECT #SQL = REPLACE(REPLACE(#SQLTemplate, 'ReplaceTableName', QUOTENAME(SchemaName) + '.'
+ QUOTENAME(TableName)), 'ReplaceColumnName', ColumnName)
FROM #Temp
WHERE RowId = #i
PRINT #SQL
EXEC SP_EXECUTESQL
#SQL,
#PARAMETERS,
#DataExists = #DataExists OUTPUT
IF #DataExists = 1
UPDATE #Temp
SET DataFound = 1
WHERE RowId = #i
SET #i = #i + 1
END
SELECT SchemaName,
TableName,
ColumnName
FROM #Temp
WHERE DataFound = 1
GO
EXEC FindMyData_String
#DataToFind='Enter Your String'
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.