Search for special characters in records in database - sql-server

I have a database in SQL Server with 100 tables inside it.
I need to write a query that parses all the rows in all the columns in all 100 tables and returns the rows that have the special characters %,#.
How do I write a query that parses all the rows in all the tables?

Maybe not so subtle solution, but is functional:
USE TSQL2012
GO
DECLARE #ColumnName VARCHAR (50)
DECLARE #TableName VARCHAR (50)
DECLARE #SchemaName VARCHAR (50)
DECLARE #SQLQuery NVARCHAR (200)
DECLARE findSpecialCharacters CURSOR
FOR
SELECT c.name, o.name, s.name from sys.columns c
INNER JOIN sys.objects o ON c.object_id = o.object_id
INNER JOIN sys.schemas s ON o.schema_id = s.schema_id
WHERE o.type = 'U'
OPEN findSpecialCharacters
FETCH NEXT FROM findSpecialCharacters
INTO #ColumnName, #TableName, #SchemaName
WHILE ##FETCH_STATUS = 0
BEGIN
SET #SQLQuery =
'SELECT ' + #ColumnName + ', * FROM ' +
#SchemaName + '.' + #TableName +
' WHERE (' + #ColumnName + ' LIKE ' +
CHAR(39) + CHAR(37) + '[,]' + CHAR(37) + CHAR(39) + ') OR (' +
#ColumnName + ' LIKE ' +
CHAR(39) + CHAR(37) + '[#]' + CHAR(37) + CHAR(39) + ') OR (' +
#ColumnName + ' LIKE ' +
CHAR(39) + CHAR(37) + '[%]' + CHAR(37) + CHAR(39) + ')'
PRINT 'Table: ' + #TableName + '; Column: ' + #ColumnName
PRINT #SQLQuery
EXEC sp_executesql #SQLQuery
FETCH NEXT FROM findSpecialCharacters
INTO #ColumnName, #TableName, #SchemaName
END
CLOSE findSpecialCharacters
DEALLOCATE findSpecialCharacters
First, I was searching for all columns in all tables, and that result set put in FOR SELECT cursor statement. If table has five columns, then my cursor will create five different result set, depending on which column is WHERE filter.
But, for distinction on which column is searching, I simple put that column as first in select list.

Related

How do I Get Maximum and Minimum Data Length for All Columns on All Tables in a SQL Server database Using One Query?

I am currently trying to get details of maximum and minimum data length (using DATALENGTH / LEN) for all columns on all tables on my SQL Server database.
Currently what I can do is I can show the details of the actual length of a column when setting up the table, maximum and minimum data length but only for one table.
I have about 50 tables that I want to check, so instead of checking each table one by one, could anyone assist in getting the result for all tables within one single query?
This is the query that I currently use (I found the query from an online source):
DECLARE #TSQL VARCHAR(MAX) = ''
DECLARE #TableName sysname = 'MyTable'
SELECT #TSQL = #TSQL + 'SELECT ' + QUOTENAME(sc.name, '''') + ' AS ColumnName,
' + QUOTENAME(t.name, '''') + ' AS DataType, ' +
QUOTENAME(sc.max_length, '''') + ' AS ActualLength,
MIN(DATALENGTH(' + QUOTENAME(sc.name) + ')) AS MinUsedLength,
MAX(DATALENGTH(' + QUOTENAME(sc.name) + ')) AS MaxUsedLength FROM '+#TableName+ char(10) +' UNION '
FROM sys.columns sc
JOIN sys.types t on t.system_type_id = sc.system_type_id and t.name != 'sysname'
WHERE sc.OBJECT_ID = OBJECT_ID(#TableName)
SET #TSQL = LEFT(#TSQL, LEN(#TSQL)-6)
EXEC(#TSQL)
DECLARE #SQL NVARCHAR(max) = N'';
SELECT #SQL = #SQL + N'SELECT '''
+ C.TABLE_SCHEMA + N''' AS TABLE_SCHEMA, '''
+ C.TABLE_NAME + N''' AS TABLE_NAME, '''
+ C.COLUMN_NAME + N''' AS COLUMN_NAME, '
+ N'MIN(DATALENGTH([' + C.COLUMN_NAME + N'])) AS MIN_LENGTH, '
+ N'MAX(DATALENGTH([' + C.COLUMN_NAME + N'])) AS MAX_LENGTH '
+ N'FROM [' + + C.TABLE_SCHEMA + N'].[' + C.TABLE_NAME
+N'] UNION ALL '
FROM INFORMATION_SCHEMA.TABLES AS T
JOIN INFORMATION_SCHEMA.COLUMNS AS C
ON T.TABLE_SCHEMA = C.TABLE_SCHEMA AND
T.TABLE_NAME = C.TABLE_NAME
WHERE TABLE_TYPE = 'BASE TABLE';
SET #SQL = LEFT(#SQL, LEN(#SQL) - 10);
EXEC (#SQL);

Compare 2 rows in MS SQL and get the columns that differ

i have searched this one out for a while, but just don't know if there is a "silver bullet" solution to what I'm looking to do. I have a table in my DB (for the sake of this discussion the actual columns are irrelevant). I want to be able to look at 2 rows from the same table and get a list of columns that are different between the 2.
I know I could write a whole bunch of TSQL to make this happen for a specific table, but I was hoping there was a built in function in SQL Server (I'm running 2008 R2) that could do this.
I know there are simple functions like CHECKSUM that will tell me if 2 rows are different, but I need the specifics of which columns are different.
Preferably I would like to make it into a UDF and pass the table name, and primary keys of the 2 rows I want compared.
Any Thoughts or Suggestions?
--EDIT-- Here is the solution I came up with:
Well, It is certainly not the most elegant solution...but it will work in a pinch.
CREATE PROCEDURE sp_Compare_Table_Rows
(
#TablePK varchar(1000), -- The Name of the Primary Key in that Table
#TableName varchar(1000), -- The Name of the Table
#PK1 int, -- The ID of the 1st table
#PK2 int -- The ID of the 2nd table
)
AS
DECLARE #Holder table
(
Column_Name varchar(250),
Different bit
)
INSERT INTO #Holder(Column_Name,Different)
select
COLUMN_NAME,0
from
LPS_DEV.INFORMATION_SCHEMA.COLUMNS
WHERE
TABLE_NAME = #TableName
and ORDINAL_POSITION >1
DECLARE #LoopedColumnName varchar(250)
DECLARE #DynamicQuery nvarchar(max)
DECLARE #ORD1 int
DECLARE #ORD2 int
SET #DynamicQuery = ''
SET #LoopedColumnName = ''
SET #ORD1 = 0
SET #ORD2 = 0
DECLARE MYCUR CURSOR FOR SELECT Column_Name FROM #Holder
OPEN MYCUR
FETCH NEXT FROM MYCUR INTO #LoopedColumnName
WHILE ##FETCH_STATUS = 0
BEGIN
SET #DynamicQuery = 'SELECT #Outer= CHECKSUM(' + #LoopedColumnName + ') FROM ' + #TableName + ' WHERE ' + #TablePK + ' = ' + CONVERT(varchar(100),#PK1)
exec sp_executesql #DynamicQuery, N'#Outer int output',#ORD1 out
SET #DynamicQuery = 'SELECT #Outer= CHECKSUM(' + #LoopedColumnName + ') FROM ' + #TableName + ' WHERE ' + #TablePK + ' = ' + CONVERT(varchar(100),#PK2)
exec sp_executesql #DynamicQuery, N'#Outer int output',#ORD2 out
IF #ORD1 <> #ORD2
BEGIN
UPDATE #Holder SET Different = 1 WHERE Column_Name = #LoopedColumnName
END
FETCH NEXT FROM MYCUR INTO #LoopedColumnName
END
CLOSE MYCUR
DEALLOCATE MYCUR
select * from #Holder
John, you can use something like this. This will display the column names -
Set the #tablename and #whereclause.
declare #tablename varchar(1000),
#cols varchar(max),
#sqlstmt nvarchar(max),
#whereclause nvarchar(max);
set #tablename = 'sometable';
set #whereclause = ' where
a.col1 = ''SOMEOTHERVALUE'' and a.datecol2 = ''19910101'' and
b.col2 = ''SOMEVALUE'' and b.datecol2 = ''19910101''
'
select #cols = stuff((
select ', case when a.' + c.name + ' = b.' + c.name
+ ' then '''' else ''' + c.name + ''' end'
from sys.columns c
inner join sys.tables t on c.object_id = t.object_id
where t.name = #tablename
for xml path ('')), 1, 1, '')
set #sqlstmt = 'select ' + #cols + ' from ' + #tablename
+ ' a, ' + #tablename + ' b ' + #whereclause
exec sp_executesql #sqlstmt
I did some enhancements on Sriram answer, here is the new script:
declare #tablename nvarchar(MAX),
#cols varchar(max) = '',
#sqlstmt nvarchar(max) = 'DECLARE #T AS TABLE (ColumnName NVARCHAR(MAX), Value NVARCHAR(MAX), Value2 NVARCHAR(MAX))',
#whereclause nvarchar(max) = '';
set #tablename = 'TABLE_NAME';
set #whereclause = ' where a.FIRST_ROW_ID = ''NUMBER'' and b.SECOND_ROW_ID = ''NUMBER'''
select #cols = (
select ' INSERT INTO #T SELECT ''' + c.name + ''', cast(a.' + c.name + ' as nvarchar(max)), cast(b.' + c.name + ' as nvarchar(max)) from ' + #tablename + ' a, ' + #tablename + ' b ' + #whereclause + ' AND cast(a.' + c.name + ' as nvarchar(max)) != cast(b.' + c.name + ' as nvarchar(max))'
from sys.columns c
inner join sys.tables t on c.object_id = t.object_id
where t.name = #tablename
for xml path (''))
set #sqlstmt += #cols + ' SELECT * FROM #T'
exec sp_executesql #sqlstmt
You need to replace 'TABLE_NAME' with your table and change the where clause variable.
The result will be like this:
ColumnName | Value | Value2
----------------------------
Id | 1 | 2
Name | Name 1 | Name 2
I have done further enhancement to Sriram Chitturi and Mohamed Noor's answer and also handled datetime comparison
ALTER PROC [dbo].[IdentifyNotMatchingColumnDataBetween2Rows] (
#table_name VARCHAR(300) = 'TableName'
,#excluded_columns VARCHAR(300) = 'Id,UpdateTimeStamp,InsertTimeStamp,IsDuplicate,NotMatchingColumns'
,#compare_row_id_1 INT = 1732340
,#compare_row_id_2 INT = 1736803
)
AS
/*
EXEC [dbo].[IdentifyNotMatchingColumnDataBetween2Rows]
*/
BEGIN
SET NOCOUNT ON;
DECLARE #cols VARCHAR(max) = ''
DECLARE #sqlstmt NVARCHAR(max) = 'DECLARE #T AS TABLE (ColumnName VARCHAR(300), Value NVARCHAR(MAX), Value2 NVARCHAR(MAX))'
DECLARE #where_clause NVARCHAR(max) = ' WHERE a.Id = ''' + CAST(#compare_row_id_1 as varchar(20)) + ''' and b.Id = ''' + CAST(#compare_row_id_2 as varchar(20)) + ''''
SELECT #cols = (
SELECT CASE
WHEN c.system_type_id = 106 --DECIMAL
OR c.system_type_id = 56 --INT
OR c.system_type_id = 48 --TINYINT
OR c.system_type_id = 52 --SMALLINT
OR c.system_type_id = 127 --BIGINT
OR c.system_type_id = 62 --FLOAT
OR c.system_type_id = 108 --NUMERIC
THEN ' INSERT INTO #T SELECT ''[' + c.name + ']'', CAST(a.[' + c.name + '] AS NVARCHAR(MAX)), CAST(b.[' + c.name + '] AS NVARCHAR(MAX)) FROM [' + #table_name + '] a WITH(NOLOCK) , [' + #table_name + '] b WITH(NOLOCK) ' + #where_clause + ' AND CAST(ISNULL(a.[' + c.name + '],' + '-1' + ') AS NVARCHAR(MAX)) != CAST(ISNULL(b.[' + c.name + '],' + '-1' + ') AS NVARCHAR(MAX))'
WHEN c.system_type_id IN (61,42) -- DATETIME / DATETIME2
THEN ' INSERT INTO #T SELECT ''[' + c.name + ']'', FORMAT(a.[' + c.name + '] ,''yyyyMMddHHmmssffff''), FORMAT(b.[' + c.name + '] ,''yyyyMMddHHmmssffff'') FROM [' + #table_name + '] a WITH(NOLOCK) , [' + #table_name + '] b WITH(NOLOCK) ' + #where_clause + ' AND FORMAT(ISNULL(a.[' + c.name + '],' + '''' + '1900-01-01' + '''' + ') ,''yyyyMMddHHmmssffff'') != FORMAT(ISNULL(b.[' + c.name + '],' + '''' + '1900-01-01' + '''' + ') ,''yyyyMMddHHmmssffff'')'
WHEN c.system_type_id = 58 --SMALLDATETIME
THEN ' INSERT INTO #T SELECT ''[' + c.name + ']'', FORMAT(a.[' + c.name + '] ,''yyyyMMddHHmmss''), FORMAT(b.[' + c.name + '] ,''yyyyMMddHHmmss'') FROM [' + #table_name + '] a WITH(NOLOCK) , [' + #table_name + '] b WITH(NOLOCK) ' + #where_clause + ' AND FORMAT(ISNULL(a.[' + c.name + '],' + '''' + '1900-01-01' + '''' + ') ,''yyyyMMddHHmmss'') != FORMAT(ISNULL(b.[' + c.name + '],' + '''' + '1900-01-01' + '''' + ') ,''yyyyMMddHHmmss'')'
ELSE
' INSERT INTO #T SELECT ''[' + c.name + ']'', CAST(a.[' + c.name + '] AS NVARCHAR(MAX)), CAST(b.[' + c.name + '] AS NVARCHAR(MAX)) FROM [' + #table_name + '] a WITH(NOLOCK) , [' + #table_name + '] b WITH(NOLOCK) ' + #where_clause + ' AND CAST(ISNULL(a.[' + c.name + '],' + '''' + '''' + ') AS NVARCHAR(MAX)) != CAST(ISNULL(b.[' + c.name + '],' + '''' + '''' + ') AS NVARCHAR(MAX))'
END
FROM sys.columns c
INNER JOIN sys.tables t ON c.object_id = t.object_id
WHERE t.name = #table_name
AND c.name NOT IN (
SELECT items
FROM dbo.Split(#excluded_columns, ',')
)
FOR XML path('')
)
SET #sqlstmt += #cols + ' SELECT * FROM #T';
--PRINT #sqlstmt;
EXEC sp_executesql #sqlstmt
END
To Execute
EXECUTE dbo.IdentifyNotMatchingColumnDataBetween2Rows 'TableName','Id,UpdateTimeStamp,InsertTimeStamp,Last Checked,IsDuplicate,NotMatchingColumns,',#row_id_1,#row_id_2;

How do I search database for text string?

Is there any way to search a whole SQL Server database for a text string?
By the whole database I mean tables, views, stored procedures, etc.
If by database you really mean absolutely everything including procedure source code, the easiest will likely be to generate a DB dump and to search for the string within the resulting file. This will be simpler than running all sorts of queries on the information schema.
Here is the code to search certain texts in stored proc
SELECT Distinct SO.Name
FROM sysobjects SO (NOLOCK)
INNER JOIN syscomments SC (NOLOCK) on SO.Id = SC.ID
AND SO.Type = 'P'
AND SC.Text LIKE '%test%'
ORDER BY SO.Name
I got the solution to display / search all tables, columns and SPs with a stored procedure:
CREATE PROC SearchAllTables
(
#SearchStr nvarchar(100)
)
AS
BEGIN
-- Copyright © 2013 Peter Nold. All rights reserved.
-- Purpose: To search all columns of all tables for a given search string
CREATE TABLE #Results (ColumnName nvarchar(370), ColumnValue nvarchar(3630))
SET NOCOUNT ON
DECLARE #TableName nvarchar(256), #ColumnName nvarchar(128), #SearchStr2 nvarchar(110), #myCount varchar(255)
SET #TableName = ''
SET #SearchStr2 = QUOTENAME('%' + #SearchStr + '%','''')
/* debug */
print '************************************************************'
print 'Starting Search For: ' + #SearchStr2
print '************************************************************'
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 QUOTENAME(COLUMN_NAME) > #ColumnName
)
IF #ColumnName IS NOT NULL
BEGIN
-- debug
print 'Searching the field: ' + #TableName + '.' + #ColumnName
INSERT INTO #Results
EXEC
(
'SELECT ''' + #TableName + '.' + #ColumnName + ''', LEFT(CONVERT(varchar(max), ' + #ColumnName + '), 3630)
FROM ' + #TableName + ' (NOLOCK) ' +
' WHERE CONVERT(varchar(max), ' + #ColumnName + ') LIKE ' + #SearchStr2
)
END
END
END
SELECT ColumnName, ColumnValue FROM #Results
SET #myCount = 'Found in #columns: ' + cast((select count(*) from #Results) AS VARCHAR)
print '************************************************************'
print #myCount
print '************************************************************'
END
/* example to search for the text METZ:
***
exec SearchAllTables 'METZ'
*/

SQLServer conditional execution within 'EXEC' if a column exists

I'm new to SQLServer scripting (normally being a C++ developer), and would really appreciate a bit of assistance.
I am attempting to perform a "find and replace" update on all tables in a SQLServer database that contain a 'PROJID' column. I am really struggling to find a way to do this that doesn't report to me:
Msg 207, Level 16, State 1, Line 1 Invalid column name 'PROJID'.
The statement I am executing is:
EXEC
(
'IF EXISTS(SELECT * FROM sys.columns WHERE name = N''PROJID'' AND Object_ID = Object_ID(N''' + #TableName + '''))' +
' BEGIN' +
' UPDATE ' + #TableName +
' SET ' + #ColumnName + ' = REPLACE(' + #ColumnName + ',''' + #ReplaceIDStr + ''',''' + #FindIDStr + ''')' +
' WHERE ' + #ColumnName + ' LIKE ''' + #ReplaceIDStr + '''' + ' AND PROJID = ''1000''' +
' END'
)
I have also tried using:
'IF COL_LENGTH(''' + #TableName + ''',''PROJID'') IS NOT NULL' +
instead of the column-exist check above. This also still gives me the "Invalid Column Name" messages.
I would be happy to take the column-exist check outside of the 'Exec' statement, but I'm not sure how to go about doing this either.
You just need to do it in a different scope.
IF EXISTS (SELECT 1 FROM sys.columns ...)
BEGIN
DECLARE #sql NVARCHAR(MAX);
SET #sql = N'UPDATE ...';
EXEC sp_executesql #sql;
END
Output the results of this query to text. Don't forget to change the values of the variables! Take the result of this and run it.
SET NOCOUNT ON
DECLARE #ColumnName VARCHAR(200) = 'ReplaceColumn'
, #ReplaceIdStr VARCHAR(200) = 'ExampleReplaceIdStr'
, #FindIdStr VARCHAR(200) = 'ExampleFindIdStr'
PRINT 'BEGIN TRAN'
PRINT 'SET XACT_ABORT ON'
SELECT
'UPDATE ' + C.TABLE_NAME + CHAR(13)
+ 'SET ' + #ColumnName + ' = REPLACE(' + #ColumnName + ', ''' + #ReplaceIdStr + ''', ''' + #FindIdStr + ''')' + CHAR(13)
+ 'WHERE ' + #ColumnName + ' LIKE ''%' + #ReplaceIdStr + '%'' AND PROJID = ''1000''' + CHAR(13)
FROM INFORMATION_SCHEMA.COLUMNS C
WHERE C.COLUMN_NAME = 'PROJID'
PRINT 'COMMIT TRAN'
SET NOCOUNT OFF
EDIT: Also, some reasoning: You said you want update all tables where they contain a column called PROJID. Your first query just says that if the table #TableName has a PROJID column, then update #ColumnName on it. But it doesn't guarantee that it has #ColumnName on it. The query I gave doesn't check that either, because I'm assuming that all tables that have PROJID also have #ColumnName. If that isn't the case, let me know and I can update the answer to check that. That you're getting an Invalid Column Name error points to #ColumnName not existing.
Your query would have updated one table (#TableName) at most, whereas the one I gave you will update every table that has PROJID. I hope that's what your going for.
EDIT 2: Here is a version that would run it all at once:
DECLARE #ColumnName VARCHAR(200) = 'Value'
, #ReplaceIdStr VARCHAR(200) = 'ExampleReplaceIdStr'
, #FindIdStr VARCHAR(200) = 'ExampleFindIdStr'
DECLARE #Sql NVARCHAR(MAX)
DECLARE UpdateCursor CURSOR FOR
SELECT
'UPDATE ' + C.TABLE_NAME
+ ' SET ' + #ColumnName + ' = REPLACE(' + #ColumnName + ', ''' + #ReplaceIdStr + ''', ''' + #FindIdStr + ''')'
+ ' WHERE ' + #ColumnName + ' LIKE ''%' + #ReplaceIdStr + '%'' AND PROJID = ''1000'''
FROM INFORMATION_SCHEMA.COLUMNS C
WHERE C.COLUMN_NAME = 'PROJID'
OPEN UpdateCursor
FETCH NEXT FROM UpdateCursor
INTO #Sql
WHILE ##FETCH_STATUS = 0
BEGIN
EXEC sp_executesql #Sql
FETCH NEXT FROM UpdateCursor
INTO #Sql
END
CLOSE UpdateCursor
DEALLOCATE UpdateCursor

delete all lines from all tables of a database

Somebody must have already written a script to delete all lines from all tables of a database.
Using DELETE command is not an option since it can takes ages on large tables.
Of course there are many examples on stackoverflow and elsewhere, but they don't work with tables using foreign keys.
Basically, the script should do this :
Store all foreign keys definition in a temporary table
delete all foreign keys
truncate all tables
restore foreign keys
I think i have it :
IF OBJECT_ID('tempdb..#ForeignKeys') IS NOT NULL
DROP TABLE #ForeignKeys;
WITH ForeignKeys AS (
SELECT
QUOTENAME(SCHEMA_NAME(t.schema_id)) + '.' + QUOTENAME(t.name) AS ParentTable
, QUOTENAME(SCHEMA_NAME(rt.schema_id)) + '.' + QUOTENAME(rt.name) AS ReferenceTable
, QUOTENAME(f.name) AS ConstraintName
, STUFF(Parent.Cols, 1, 1, '') AS ParentColumns
, STUFF(Reference.Cols, 1, 1, '') AS ReferenceColumns
, REPLACE(f.update_referential_action_desc, '_', ' ') AS UpdateAction
, REPLACE(f.delete_referential_action_desc, '_', ' ') AS DeleteAction
FROM
sys.tables AS t
LEFT JOIN sys.foreign_keys AS f
ON f.parent_object_id = t.object_id
AND f.type = 'F'
LEFT JOIN sys.tables AS rt
ON f.referenced_object_id = rt.object_id
CROSS APPLY
(
SELECT
',' + QUOTENAME(COL_NAME(fc.parent_object_id, fc.parent_column_id))AS [text()]
FROM
sys.foreign_key_columns AS fc
WHERE
fc.constraint_object_id = f.object_id
ORDER BY
fc.constraint_column_id
FOR XML PATH('')
) Parent(Cols)
CROSS APPLY
(
SELECT
',' + QUOTENAME(COL_NAME(fc.referenced_object_id, fc.referenced_column_id)) AS [text()]
FROM
sys.foreign_key_columns AS fc
WHERE
fc.constraint_object_id = f.object_id
ORDER BY
fc.constraint_column_id
FOR XML PATH('')
) Reference(Cols)
)
SELECT
ParentTable AS TableName
, 'ALTER TABLE ' + ParentTable + ' DROP CONSTRAINT ' + ConstraintName AS DropCmd
, 'TRUNCATE TABLE ' + ParentTable AS TruncateCmd
, 'ALTER TABLE ' + ParentTable + ' ADD CONSTRAINT ' + ConstraintName + ' FOREIGN KEY('
+ ParentColumns + ') REFERENCES ' + ReferenceTable + ' (' + ReferenceColumns
+ ') ON UPDATE ' + UpdateAction
+ ' ON DELETE ' + DeleteAction COLLATE SQL_Latin1_General_CP1_CI_AS AS CreateCmd
INTO
#ForeignKeys
FROM
ForeignKeys
ORDER BY
1;
-- SELECT * FROM #ForeignKeys
DECLARE #TableName SYSNAME
DECLARE #Sql NVARCHAR(MAX)
-- Drop all constraints
DECLARE FkCursor CURSOR FOR
SELECT
TableName
, DropCmd
FROM
#ForeignKeys
WHERE
DropCmd IS NOT NULL
OPEN FkCursor
FETCH NEXT FROM FkCursor INTO #TableName, #Sql
WHILE ##FETCH_STATUS = 0
BEGIN
PRINT #TableName + ' : ' + #sql
EXEC sp_executesql #Sql
FETCH NEXT FROM FkCursor INTO #TableName, #Sql
END
CLOSE FkCursor
DEALLOCATE FkCursor
-- Truncate all tables
DECLARE FkCursor CURSOR FOR
SELECT
TableName
, TruncateCmd
FROM
#ForeignKeys
OPEN FkCursor
FETCH NEXT FROM FkCursor INTO #TableName, #Sql
WHILE ##FETCH_STATUS = 0
BEGIN
PRINT #TableName + ' : ' + #sql
EXEC sp_executesql #Sql
FETCH NEXT FROM FkCursor INTO #TableName, #Sql
END
CLOSE FkCursor
DEALLOCATE FkCursor
-- Create all foreign keys
DECLARE FkCursor CURSOR FOR
SELECT
TableName
, CreateCmd
FROM
#ForeignKeys
WHERE
CreateCmd IS NOT NULL
OPEN FkCursor
FETCH NEXT FROM FkCursor INTO #TableName, #Sql
WHILE ##FETCH_STATUS = 0
BEGIN
PRINT #TableName + ' : ' + #sql
EXEC sp_executesql #Sql
FETCH NEXT FROM FkCursor INTO #TableName, #Sql
END
CLOSE FkCursor
DEALLOCATE FkCursor
DROP TABLE #ForeignKeys;
DECLARE #drop nvarchar(max) = N'',
#truncate nvarchar(max) = N'',
#create nvarchar(max) = N'';
;WITH x AS
(
SELECT id = f.[object_id],
cname = QUOTENAME(f.name),
ctable = QUOTENAME(OBJECT_SCHEMA_NAME(f.parent_object_id))
+ N'.' + QUOTENAME(OBJECT_NAME(f.parent_object_id)),
ccol = QUOTENAME(COL_NAME(fc.parent_object_id,fc.parent_column_id)),
rtable = QUOTENAME(OBJECT_SCHEMA_NAME(f.referenced_object_id))
+ N'.' + QUOTENAME(OBJECT_NAME(f.referenced_object_id)),
rcol = QUOTENAME(COL_NAME(fc.referenced_object_id,fc.referenced_column_id)),
ou = f.update_referential_action_desc COLLATE SQL_Latin1_General_CP1_CI_AS,
od = f.delete_referential_action_desc COLLATE SQL_Latin1_General_CP1_CI_AS
FROM sys.foreign_keys AS f
INNER JOIN sys.foreign_key_columns AS fc
ON f.[object_id] = fc.constraint_object_id
-- where clause to leave out certain tables here
),
y AS
(
SELECT
d = CHAR(13) + CHAR(10) + N'ALTER TABLE ' + ctable + N' DROP CONSTRAINT ' + cname + ';',
c = CHAR(13) + CHAR(10) + N'ALTER TABLE ' + ctable + N' ADD CONSTRAINT ' + cname
+ ' FOREIGN KEY (' + STUFF((SELECT N',' + ccol FROM x AS x2
WHERE x2.id = x.id FOR XML PATH(''),
TYPE).value(N'./text()[1]', N'nvarchar(max)'), 1, 1, N'')
+ N') REFERENCES ' + rtable + N'(' + STUFF((SELECT N',' + rcol FROM x AS x3
WHERE x3.id = x.id FOR XML PATH(''),
TYPE).value(N'./text()[1]', N'nvarchar(max)'), 1, 1, '') + N')'
+ CASE WHEN od <> N'NO_ACTION' THEN
' ON DELETE ' + REPLACE(od, N'SET_', N'SET ') ELSE N'' END
+ CASE WHEN ou <> N'NO_ACTION' THEN
' ON UPDATE ' + REPLACE(ou, N'SET_', N'SET ') ELSE N'' END
FROM x
)
SELECT
#drop = #drop + d,
#create = #create + c
FROM y GROUP BY d,c;
SELECT #truncate = #truncate + CHAR(13) + CHAR(10) + N'TRUNCATE TABLE '
+ QUOTENAME(SCHEMA_NAME(schema_id)) + N'.' + QUOTENAME(name) + N';'
FROM sys.tables
-- where clause to leave out certain tables here
;
-- use results to text. Note that for 200 tables you won't be able to
-- manually inspect the entire script in Management Studio because it
-- will only show a certain number of characters depending on settings.
SELECT #drop;
SELECT #truncate;
SELECT #create;
-- when you are happy, uncomment these:
--EXEC sys.sp_executesql #drop;
--EXEC sys.sp_executesql #truncate;
--EXEC sys.sp_executesql #create;
Right click on the object(in the object explorer) and click Script as--> drop to. Use the same method and Script as--> Create to. This should give you the scripts for Dropping as well as creating all the objects in your database. Run them in the sequence you like.
Or if you have a lot of tables and objects, you can right click on the database--> go to tasks and click on Generate Scripts.

Resources