I'm trying to loop through all non system databases and run a stored procedure. This stored procedure exists in all of the user databases.
This is what I have found so far:
DECLARE #command varchar(1000)
SELECT #command = 'USE ? SELECT name FROM sysobjects WHERE xtype = ''U'' ORDER BY name'
USE #command;
GO
EXECUTE Support.CleanIndiciesAndShrinkDatabase;
GO
I get an error this error:
Msg 102, Level 15, State 1, Line 3
Incorrect syntax near '#command'.
Msg 2812, Level 16, State 62, Line 1
Could not find stored procedure 'Support.CleanIndiciesAndShrinkDatabase'.
Any suggestions on fixing this?
Try the following
DECLARE #command varchar(1000)
DECLARE #spName VARCHAR(50)
SET #spName = 'Support.CleanIndiciesAndShrinkDatabase'
SELECT #command = 'IF ''?'' NOT IN(''master'', ''model'', ''msdb'', ''tempdb'')
BEGIN
USE ?
IF EXISTS(SELECT TOP 1 1 FROM sys.procedures AS P WHERE p.name = ''' + #spName + ''')
BEGIN
PRINT ''running '+ #spName + ' on '' + DB_NAME()
EXEC ' +#spName+'
END
ELSE
BEGIN
PRINT ''' + #spName + ' was on found on database '' + DB_NAME()''
END
END '
EXEC sp_MSforeachdb #command
It will run on all non-system databases.
Now, the error you get means that SQL Server cannot find the stored procedure. You could fix this by creating the stored procedure on any database that does not have it yet and then running it.
So a better query would be
DECLARE #command varchar(1000)
DECLARE #schemaName VARCHAR(50)
DECLARE #spName VARCHAR(50)
SET #schemaName = 'Support'
SET #spName = 'CleanIndiciesAndShrinkDatabase'
SELECT #command = 'IF ''?'' NOT IN(''master'', ''model'', ''msdb'', ''tempdb'')
BEGIN
USE ?
IF NOT EXISTS(SELECT TOP 1 1
FROM sys.procedures AS P
INNER JOIN sys.schemas AS S ON S.schema_id = P.schema_id
WHERE p.name = ''' + #spName + '''
AND s.name = ''' + #schemaName + ''')
BEGIN
PRINT ''creating '+ #spName + ' on '' + DB_NAME()
IF NOT EXISTS ( SELECT TOP 1 1
FROM sys.schemas AS S
WHERE S.name = ''' + #schemaName + ''' )
BEGIN
PRINT ''CREATING SCHEMA ' + #schemaName + '''
EXEC ( '' CREATE SCHEMA ' + #schemaName + ''' );
END;
EXEC ( ''
CREATE PROCEDURE ' + #schemaName + '.' + #spName + '
AS
BEGIN
-- SP CODE GOES HERE
-- SELECT COUNT(*) FROM SYS.TABLES --uncomment this for check
END
'' );
END
PRINT ''running '+ #spName + ' on '' + DB_NAME()
EXEC ' + #schemaName + '.' + #spName +'
END '
EXEC sp_MSforeachdb #command
You can try this:
Create PROC PROC_NAME
AS
BEGIN
DECLARE #name nvarchar(50)
declare #cursor cursor
set #cursor = CURSOR FAST_FORWARD FOR select name from sys.databases where database_id > 4
open #cursor
FETCH NEXT FROM #cursor INTO #name
WHILE ##FETCH_STATUS = 0
BEGIN
DECLARE #use nvarchar(50) = 'USE '
SET #use = #use + #name
Declare #query nvarchar(max) = #use + ' exec Your_PROC'
EXEC sp_executesql #query
FETCH NEXT FROM #cursor INTO #name
END
CLOSE #cursor
DEALLOCATE #cursor
END
Try something like this:
DECLARE #DynamicTSQLStatement NVARCHAR(MAX);
SELECT #DynamicTSQLStatement = STUFF
(
(
SELECT 'USE [' + [name] + ']; EXECUTE Support.CleanIndiciesAndShrinkDatabase;'
FROM [sys].[databases]
WHERE [name] NOT IN ('master', 'tempdb', 'model', 'msdb')
FOR XML PATH(''), TYPE
).value('.', 'NVARCHAR(MAX)')
,1
,1
,''
);
EXECUTE sp_executesql #DynamicTSQLStatement;
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.
I have created a script to compare the tables of two databases to find differences. I want to be able to manually set two variables (one for each database) and have the 'USE' statement use the variable value for one of the databases but it changes context and does work correctly.
This is what I am trying to use to populating a variable (#Use) with the USE code to execute
--set #Use = 'USE ' + #NewProdDB + ';SELECT name FROM sys.tables'
--EXEC (#Use)
This is the entire query:
--========================================================================================================
-- Used to find table values in the test upgrade system database not found the newly upgraded system
-- database. Make sure change the system database names before running the query.
-- Also, select the upgraded database to run against
--========================================================================================================
DECLARE #NewProdDB VARCHAR(100)
DECLARE #TestUpgradeDB VARCHAR(100)
DECLARE #Columns VARCHAR (MAX)
DECLARE #Query VARCHAR(MAX)
DECLARE #ResultsTest VARCHAR(MAX)
DECLARE #SetResultsCursor NVARCHAR(MAX)
DECLARE #Fetcher NVARCHAR(MAX)
DECLARE #Use NVARCHAR(50)
DECLARE #ListOfTables VARCHAR(100)
DECLARE #WTF NVARCHAR(max)
DECLARE #rescanCode nvarchar(max)
/* Enter Upgraded system DB here */
SET #NewProdDB = 'zSBSSYS'
/* Enter Test Upgrade system DB here */
SET #TestUpgradeDB = 'TESTzSBSSYS'
--set #Use = 'USE ' + #NewProdDB + ';SELECT name FROM sys.tables'
--EXEC (#Use)
SET NOCOUNT ON
set #rescanCode = 'DECLARE recscan CURSOR FOR
SELECT TABLE_NAME FROM ' + #TestUpgradeDB + '.INFORMATION_SCHEMA.TABLES
WHERE TABLE_NAME NOT LIKE ''Mbf%'' AND TABLE_TYPE = ''BASE TABLE''
ORDER BY TABLE_NAME'
exec (#rescanCode)
OPEN recscan
FETCH NEXT FROM recscan INTO #ListOfTables
WHILE ##fetch_status = 0
BEGIN
BEGIN TRY
/* START Table column query */
Declare #Table varchar(60)
set #Table = #ListOfTables
set #table = (SELECT top 1 name FROM sys.tables where name = #Table)
DECLARE
#sql1 nvarchar(max) = ''
,#INTOColumns NVARCHAR(MAX)=''
,#Where nvarchar(max) = ''
,#ColumnID Int
,#Column Varchar(8000)
,#Type Varchar(8000)
,#Length Int
,#del1 varchar(2) = ','
,#CRLF bit = 1
,#aliasfield varchar(5) = '[a].'
DECLARE CSR_Attributes CURSOR FOR
SELECT
[ColumnID] = Col.column_id,
[Column] = Col.Name,
[Type] = [types].name,
[Length] = Col.max_length
FROM sys.objects Obj, sys.columns Col, sys.types [types]
WHERE Obj.OBJECT_ID = Col.OBJECT_ID AND Obj.TYPE = 'U'
AND Col.system_type_id = [types].system_type_id
AND Obj.name = #table
AND Col.name <> 'tstamp'
ORDER BY Obj.name, Col.column_id, Col.name
OPEN CSR_Attributes
FETCH NEXT FROM CSR_Attributes INTO #ColumnID, #Column, #Type, #Length
WHILE ##FETCH_STATUS = 0
BEGIN
set #sql1 += #column + #del1
set #Where += 'b.' + #column + '=a.' + #column + ' and '
set #INTOColumns += '#INTOcol,'
FETCH NEXT FROM CSR_Attributes INTO #ColumnID, #Column, #Type, #Length
END
CLOSE CSR_Attributes
DEALLOCATE CSR_Attributes
SET #Columns = SUBSTRING(#sql1,1,len(#sql1)-1) -- get rid of last comma
SET #Where = SUBSTRING(#Where,1,len(#Where)-4) -- get rid of last 'and'
SET #INTOColumns = SUBSTRING(#INTOColumns,1,len(#INTOColumns)-1) -- get rid of last comma
/* END Table column query */
/* Create SELECT statement here */
SET #ResultsTest='SELECT TOP 1 ' + #Columns + '
FROM ' + #TestUpgradeDB + '..' + #Table + ' A
WHERE NOT EXISTS
(SELECT ' + #Columns + '
FROM ' + #NewProdDB + '..' + #Table + ' B WHERE ' + #Where + ')'
SET #SetResultsCursor = 'DECLARE DataReturned CURSOR FOR ' + #ResultsTest
exec (#SetResultsCursor)
OPEN DataReturned
SET #Fetcher = 'DECLARE #INTOcol NVARCHAR(Max)
FETCH NEXT FROM DataReturned INTO ' + #INTOColumns
exec (#Fetcher)
if ##FETCH_STATUS = 0
begin
CLOSE DataReturned
DEALLOCATE DataReturned
SET #Query='SELECT ' + #Columns + '
FROM ' + #TestUpgradeDB + '..' + #Table + ' A WHERE NOT EXISTS
(SELECT ' + #Columns + ' FROM ' + #NewProdDB + '..' + #Table + ' B WHERE ' + #Where + ')'
select #Table
exec (#Query)
end
else
begin
CLOSE DataReturned
DEALLOCATE DataReturned
end
end try
begin catch
--SELECT ERROR_MESSAGE() AS ErrorMessage;
end catch
FETCH NEXT FROM recscan INTO #ListOfTables
end
CLOSE recscan
DEALLOCATE recscan
SET NOCOUNT OFF
You can't do this:
DECLARE #DB varchar(10) = 'beep';
DECLARE #USE varchar(50) = 'USE '+ #DB;
EXEC sp_sqlexec #USE;
SELECT blah FROM bloop
Database context is only used during the #USE sql, then reverts
You can do this:
DECLARE #DB varchar(10) = 'beep';
DECLARE #SQL varchar(50) = 'USE '+#DB+'; SELECT blah FROM bloop;'
EXEC sp_sqlexec #USE;
That aside, look into SQL Server Data Tools (SSDT)
It does exactly what it seems you are trying to do, schema and/or data compare between databases, and it's very easy to use.
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.
I have hundreds of procedures auto generated by DataSync.
I don't have the time and sense to delete them manually.
They all start with DataSync.
Is there a way to delete all stored procedures where the name start with DataSync.?
Use the information_schema.routines (which is fairly standard across RDBMSs such as MSSQL,Mysql):
If your proc names start "DataSync." then they are probably in a schema, so you can find them with:
select
'DROP PROCEDURE [' + routine_schema + '].[' + routine_name + ']'
from
information_schema.routines where routine_schema = 'DataSync' and routine_type = 'PROCEDURE'
If your proc names start "DataSync" then you can find them with:
select
'DROP PROCEDURE [' + routine_schema + '].[' + routine_name + ']'
from
information_schema.routines where routine_name like 'DataSync%' and routine_type = 'PROCEDURE'
If you wanted to execute all these drop statements, you can build a single execute using FOR XML PATH as follows:
declare #sql varchar(max)
set #sql = (
select
'DROP PROCEDURE [' + routine_schema + '].[' + routine_name + '] '
from
information_schema.routines where routine_schema = 'DataSync' and routine_type = 'PROCEDURE'
FOR XML PATH ('')
)
exec (#sql)
Assuming you mean SQL Server when you specify "SQL" - then the easiest way is this: run this query:
SELECT
name,
DropCmd = 'DROP PROCEDURE DataSync.' + name
FROM sys.procedures
WHERE
schema_id = SCHEMA_ID('DataSync')
and the even "lazier" version would be to use a cursor to do this automatically for you:
DECLARE DropSpCursor CURSOR FAST_FORWARD FOR
SELECT
name
FROM sys.procedures
WHERE schema_id = SCHEMA_ID('DataSync')
DECLARE #StoredProcName sysname
DECLARE #DropStatement NVARCHAR(1000)
OPEN DropSpCursor
FETCH NEXT FROM DropSpCursor INTO #StoredProcName, #SchemaName
WHILE (##fetch_status <> -1)
BEGIN
IF (##fetch_status <> -2)
BEGIN
SET #DropStatement = N'DROP PROCEDURE DataSync.' + #StoredProcName
EXEC(#DropStatement)
END
FETCH NEXT FROM DropSpCursor INTO #StoredProcName
END
CLOSE DropSpCursor
DEALLOCATE DropSpCursor
No need for XML or loops:
declare #sql varchar(max) = ''
select #sql += 'drop procedure [' + routine_schema + '].[' + routine_name + '];'
from information_schema.routines where routine_schema = 'DataSync' and routine_type = 'PROCEDURE'
exec(#sql)
DECLARE #name AS VARCHAR(max)
DECLARE MyCursor CURSOR FAST_FORWARD READ_ONLY FOR
SELECT name FROM sys.objects WHERE type='P' AND schema_id=SCHEMA_ID('DataSync')
OPEN MyCursor
FETCH NEXT FROM MyCursor INTO #name
WHILE ##FETCH_STATUS = 0
BEGIN
EXEC('DROP PROCEDURE DataSync.' + #name)
FETCH NEXT FROM MyCursor INTO #name
END
CLOSE MyCursor
DEALLOCATE MyCursor
EDIT: changed where clause since it turned out DataSync is a schema name.
I've been using this short script to clear all SPs from a given schema (when using SQL Server). It iterates direct sys.procedures.
DECLARE #schema VARCHAR(100)
SET #schema = 'DataSync'
DECLARE #CurrentStatement AS VARCHAR(MAX)
SET #CurrentStatement = (SELECT TOP(1) 'DROP PROCEDURE [' + #schema + '].[' + name + ']'
FROM sys.procedures
WHERE schema_id = SCHEMA_ID(#schema))
WHILE #CurrentStatement IS NOT NULL
BEGIN
EXEC (#CurrentStatement)
SET #CurrentStatement = (SELECT TOP(1) 'DROP PROCEDURE [' + #schema + '].[' + name + ']'
FROM sys.procedures
WHERE schema_id = SCHEMA_ID(#schema))
END
The premise is very similar to the answer provided by marc_s; however doesn't utilize a cursor for the iteration. While there's a record in sys.procedures matching our schema, we need to delete it.
try this with sql2012 or above,
this will be help to delete all objects by selected schema
keep 'P' and remove rest for stored procedure only (o.type IN ('P')
DECLARE #MySchemaName VARCHAR(50)='dbo', #sql VARCHAR(MAX)='';
DECLARE #SchemaName VARCHAR(255), #ObjectName VARCHAR(255), #ObjectType VARCHAR(255), #ObjectDesc VARCHAR(255), #Category INT;
DECLARE cur CURSOR FOR
SELECT (s.name)SchemaName, (o.name)ObjectName, (o.type)ObjectType,(o.type_desc)ObjectDesc,(so.category)Category
FROM sys.objects o
INNER JOIN sys.schemas s ON o.schema_id = s.schema_id
INNER JOIN sysobjects so ON so.name=o.name
WHERE s.name = #MySchemaName
AND so.category=0
AND o.type IN ('P','PC','U','V','FN','IF','TF','FS','FT','PK','TT')
OPEN cur
FETCH NEXT FROM cur INTO #SchemaName,#ObjectName,#ObjectType,#ObjectDesc,#Category
SET #sql='';
WHILE ##FETCH_STATUS = 0 BEGIN
IF #ObjectType IN('FN', 'IF', 'TF', 'FS', 'FT') SET #sql=#sql+'Drop Function '+#MySchemaName+'.'+#ObjectName+CHAR(13)
IF #ObjectType IN('V') SET #sql=#sql+'Drop View '+#MySchemaName+'.'+#ObjectName+CHAR(13)
IF #ObjectType IN('P') SET #sql=#sql+'Drop Procedure '+#MySchemaName+'.'+#ObjectName+CHAR(13)
IF #ObjectType IN('U') SET #sql=#sql+'Drop Table '+#MySchemaName+'.'+#ObjectName+CHAR(13)
--PRINT #ObjectName + ' | ' + #ObjectType
FETCH NEXT FROM cur INTO #SchemaName,#ObjectName,#ObjectType,#ObjectDesc,#Category
END
CLOSE cur;
DEALLOCATE cur;
SET #sql=#sql+CASE WHEN LEN(#sql)>0 THEN 'Drop Schema '+#MySchemaName+CHAR(13) ELSE '' END
PRINT #sql
EXECUTE (#sql)
I want to update some rows which be include some null fields.
How can I update these rows in SQL Server?
I am asking because a rows has got 180 fields. :)
Please help me.
You can use dynamic SQL to generate a script to run. The following will probably need tweaking for you to exclude columns that you don't want to update etc.
DECLARE #TableName nvarchar(500) = '[dbo].[T]'
DECLARE #DynSql nvarchar(max)
SELECT #DynSql = ISNULL(#DynSql+',','') + QUOTENAME(name) + '= ISNULL(' + QUOTENAME(name) + ',0)'
FROM sys.columns
WHERE object_id = OBJECT_ID(#TableName)
SET #DynSql = 'UPDATE ' + #TableName + 'SET ' + #DynSql
PRINT #DynSql
--EXEC(#DynSql)
I think I understand what you are asking. This will generate an update statement for each column in your table that will set it's value to 0 if it's value is null.
declare #tableName nvarchar(100)
declare #querys varchar(max)
set #querys = ''
set #tableName = 'YOUR TABLE NAME HERE'
select #querys = #querys + 'update ' + #tableName + ' set ' +
QUOTENAME(t.[name]) + '=0 where ' + QUOTENAME(t.[name]) + ' is null;'
from (SELECT [name] FROM syscolumns
WHERE id = (SELECT id
FROM sysobjects
WHERE type = 'U'
AND [NAME] = #tableName))t
select #querys
execute sp_executesql #sqlQuery
Well It is an old post, but I recently had this problem and wanted a dynamic SQL query using the above solution that performed the update depending on column types.
USE [YOUR DATABASE]
DECLARE #tableName nvarchar(100)
DECLARE #name varchar(50)
DECLARE #dtype varchar(50)
DECLARE #CMD NVARCHAR (200)
SET #tableName = [YOUR TABLE NAME]
DECLARE db_cursor CURSOR FOR
SELECT c.name, t.name AS Dtype
FROM sys.columns c
INNER JOIN sys.types t
ON t.system_type_id = c.system_type_id
WHERE c.[object_id] =
(SELECT [object_id] FROM sys.objects WHERE type = 'U' AND [NAME] = #tableName)
OPEN db_cursor
FETCH NEXT FROM db_cursor INTO #name, #Dtype
WHILE ##FETCH_STATUS = 0 BEGIN
SET #CMD = 'UPDATE ' + #tableName + ' SET ' + quotename(#name) +' = ' +
(CASE
WHEN (#Dtype = 'bit') THEN '0'
WHEN (#Dtype = 'int') THEN '0'
WHEN (#Dtype = 'decimal') THEN '0'
WHEN (#Dtype = 'date') THEN '''1/1/1900'''
WHEN (#Dtype = 'datetime') THEN '''1/1/1900'''
WHEN (#Dtype = 'uniqueidentifier') THEN '00000000-0000-0000-0000-000000000000'
ELSE ''''''
END )
+ ' WHERE ' + quotename(#name) +' IS NULL'
PRINT #CMD
EXEC sp_executeSQL #cmd
FETCH NEXT FROM db_cursor INTO #name, #Dtype
END
CLOSE db_cursor
DEALLOCATE db_cursor