Drop all objects in SQL DB? - sql-server

Does anyone have a script that will drop all objects in a SQL Server DB?
I currently don't have rights to drop and create DBs on the server so am looking for a script to take me back to 'square one'
I've seen some on the web, but they don't do things in the right order or they don't remove everything.

If you use schemas you may find the following script useful:
SET NOCOUNT ON;
DECLARE #OnlyInSchema sysname;
-- Set this to a value to only drop objects in one schema.
-- SET #OnlyInSchema = N'';
DECLARE #Commands TABLE (
[Description] NVARCHAR(MAX),
[Line] NVARCHAR(MAX)
);
DECLARE #Drops TABLE (
[Type] NVARCHAR(2),
[Template] NVARCHAR(MAX)
);
-- -- -- -- -- OBJECTS NOT ASSOCIATED WITH TABLES -- -- -- -- --
INSERT INTO #Drops
SELECT N'AF', N'DROP AGGREGATE $S.$O;' UNION
SELECT N'FN', N'DROP FUNCTION $S.$O;' UNION
SELECT N'FS', N'DROP FUNCTION $S.$O;' UNION
SELECT N'FT', N'DROP FUNCTION $S.$O;' UNION
SELECT N'IF', N'DROP FUNCTION $S.$O;' UNION
SELECT N'P', N'DROP PROCEDURE $S.$O;' UNION
SELECT N'SN', N'DROP SYNONYM $S.$O;' UNION
SELECT N'SQ', N'DROP QUEUE $S.$O;' UNION
SELECT N'TR', N'DROP TRIGGER $S.$O;' UNION
SELECT N'TT', N'DROP TYPE $S.$O;' UNION
SELECT N'TF', N'DROP FUNCTION $S.$O;';
INSERT INTO #Commands
SELECT QUOTENAME(RTRIM([S].[name])) + '.' + QUOTENAME(RTRIM([O].[name])),
REPLACE(REPLACE([D].[Template], '$S', QUOTENAME(RTRIM([S].[name]))), '$O', QUOTENAME(RTRIM([O].[name])))
FROM [sys].[objects] AS [O]
INNER JOIN [sys].[schemas] AS [S] ON [O].[schema_id] = [S].[schema_id]
INNER JOIN #Drops AS [D] ON [O].[type] COLLATE Latin1_General_CS_AS = [D].[Type] COLLATE Latin1_General_CS_AS
WHERE (#OnlyInSchema IS NULL OR [S].[name] COLLATE Latin1_General_CS_AS = #OnlyInSchema)
AND [S].[name] COLLATE Latin1_General_CS_AS <> 'sys'
AND [O].[is_ms_shipped] = 0;
-- -- -- -- -- OBJECTS ASSOCIATED WITH TABLES -- -- -- -- --
DELETE FROM #Drops;
INSERT INTO #Drops
SELECT N'C', N'ALTER TABLE $TS.$TO DROP CONSTRAINT $O;' UNION
SELECT N'D', N'ALTER TABLE $TS.$TO DROP CONSTRAINT $O;' UNION
SELECT N'F', N'ALTER TABLE $TS.$TO DROP CONSTRAINT $O;' UNION
SELECT N'PK', N'ALTER TABLE $TS.$TO DROP CONSTRAINT $O;';
INSERT INTO #Commands
SELECT QUOTENAME(RTRIM([S].[name])) + '.' + QUOTENAME(RTRIM([PO].[name])) + '::' + QUOTENAME(RTRIM([O].[name])),
REPLACE(REPLACE(REPLACE([D].[Template], '$TS', QUOTENAME(RTRIM([S].[name]))), '$O', QUOTENAME(RTRIM([O].[name]))), '$TO', QUOTENAME(RTRIM([PO].[name])))
FROM [sys].[objects] AS [O]
INNER JOIN [sys].[objects] AS [PO] ON [O].[parent_object_id] = [PO].[object_id]
INNER JOIN [sys].[schemas] AS [S] ON [PO].[schema_id] = [S].[schema_id]
INNER JOIN #Drops AS [D] ON [O].[type] COLLATE Latin1_General_CS_AS = [D].[Type] COLLATE Latin1_General_CS_AS
WHERE (#OnlyInSchema IS NULL OR [S].[name] COLLATE Latin1_General_CS_AS = #OnlyInSchema)
AND [S].[name] COLLATE Latin1_General_CS_AS <> 'sys'
AND [O].[is_ms_shipped] = 0;
-- -- -- -- -- ACTUAL DROP -- -- -- -- --
DELETE FROM #Drops;
INSERT INTO #Drops
SELECT N'U', N'DROP TABLE $S.$O;' UNION
SELECT N'V', N'DROP TABLE $S.$O;';
INSERT INTO #Commands
SELECT QUOTENAME(RTRIM([S].[name])) + '.' + QUOTENAME(RTRIM([O].[name])),
REPLACE(REPLACE([D].[Template], '$S', QUOTENAME(RTRIM([S].[name]))), '$O', QUOTENAME(RTRIM([O].[name])))
FROM [sys].[objects] AS [O]
INNER JOIN [sys].[schemas] AS [S] ON [O].[schema_id] = [S].[schema_id]
INNER JOIN #Drops AS [D] ON [O].[type] COLLATE Latin1_General_CS_AS = [D].[Type] COLLATE Latin1_General_CS_AS
WHERE (#OnlyInSchema IS NULL OR [S].[name] COLLATE Latin1_General_CS_AS = #OnlyInSchema)
AND [S].[name] COLLATE Latin1_General_CS_AS <> 'sys'
AND [O].[is_ms_shipped] = 0;
-- -- -- -- -- TABLES -- -- -- -- --
DECLARE #Description NVARCHAR(MAX);
DECLARE #Message NVARCHAR(MAX);
DECLARE #Command NVARCHAR(MAX);
DECLARE CommandCursor CURSOR FOR
SELECT [Description], [Line] FROM #Commands;
OPEN CommandCursor;
FETCH NEXT FROM CommandCursor INTO #Description, #Command;
WHILE ##FETCH_STATUS = 0
BEGIN
SET #Message = N'Dropping ' + #Description + '...';
PRINT #Message;
BEGIN TRY
EXEC sp_executesql #Command;
END TRY
BEGIN CATCH
SET #Message = N'Failed to drop ' + #Description + ':';
PRINT #Message;
PRINT ERROR_MESSAGE()
END CATCH
FETCH NEXT FROM CommandCursor INTO #Description, #Command;
END
CLOSE CommandCursor;
DEALLOCATE CommandCursor;

I found this code on "http://kashyapmakadia.blogspot.com/2009/08/drop-everything-in-sql-server-2005.html" and tried it and it worked just find!! You can find the code there, but if you're in hurry, the code is:
/* Drop all non-system stored procs */
DECLARE #name VARCHAR(128)
DECLARE #SQL VARCHAR(254)
SELECT #name = (SELECT TOP 1 [name] FROM sysobjects WHERE [type] = 'P' AND category = 0 ORDER BY [name])
WHILE #name is not null
BEGIN
SELECT #SQL = 'DROP PROCEDURE [' + RTRIM(#name) +']'
EXEC (#SQL)
PRINT 'Dropped Procedure: ' + #name
SELECT #name = (SELECT TOP 1 [name] FROM sysobjects WHERE [type] = 'P' AND category = 0 AND [name] > #name ORDER BY [name])
END
GO
/* Drop all views */
DECLARE #name VARCHAR(128)
DECLARE #SQL VARCHAR(254)
SELECT #name = (SELECT TOP 1 [name] FROM sysobjects WHERE [type] = 'V' AND category = 0 ORDER BY [name])
WHILE #name IS NOT NULL
BEGIN
SELECT #SQL = 'DROP VIEW [' + RTRIM(#name) +']'
EXEC (#SQL)
PRINT 'Dropped View: ' + #name
SELECT #name = (SELECT TOP 1 [name] FROM sysobjects WHERE [type] = 'V' AND category = 0 AND [name] > #name ORDER BY [name])
END
GO
/* Drop all functions */
DECLARE #name VARCHAR(128)
DECLARE #SQL VARCHAR(254)
SELECT #name = (SELECT TOP 1 [name] FROM sysobjects WHERE [type] IN (N'FN', N'IF', N'TF', N'FS', N'FT') AND category = 0 ORDER BY [name])
WHILE #name IS NOT NULL
BEGIN
SELECT #SQL = 'DROP FUNCTION [' + RTRIM(#name) +']'
EXEC (#SQL)
PRINT 'Dropped Function: ' + #name
SELECT #name = (SELECT TOP 1 [name] FROM sysobjects WHERE [type] IN (N'FN', N'IF', N'TF', N'FS', N'FT') AND category = 0 AND [name] > #name ORDER BY [name])
END
GO
/* Drop all Foreign Key constraints */
DECLARE #name VARCHAR(128)
DECLARE #constraint VARCHAR(254)
DECLARE #SQL VARCHAR(254)
SELECT #name = (SELECT TOP 1 TABLE_NAME FROM INFORMATION_SCHEMA.TABLE_CONSTRAINTS WHERE constraint_catalog=DB_NAME() AND CONSTRAINT_TYPE = 'FOREIGN KEY' ORDER BY TABLE_NAME)
WHILE #name is not null
BEGIN
SELECT #constraint = (SELECT TOP 1 CONSTRAINT_NAME FROM INFORMATION_SCHEMA.TABLE_CONSTRAINTS WHERE constraint_catalog=DB_NAME() AND CONSTRAINT_TYPE = 'FOREIGN KEY' AND TABLE_NAME = #name ORDER BY CONSTRAINT_NAME)
WHILE #constraint IS NOT NULL
BEGIN
SELECT #SQL = 'ALTER TABLE [' + RTRIM(#name) +'] DROP CONSTRAINT ' + RTRIM(#constraint)
EXEC (#SQL)
PRINT 'Dropped FK Constraint: ' + #constraint + ' on ' + #name
SELECT #constraint = (SELECT TOP 1 CONSTRAINT_NAME FROM INFORMATION_SCHEMA.TABLE_CONSTRAINTS WHERE constraint_catalog=DB_NAME() AND CONSTRAINT_TYPE = 'FOREIGN KEY' AND CONSTRAINT_NAME <> #constraint AND TABLE_NAME = #name ORDER BY CONSTRAINT_NAME)
END
SELECT #name = (SELECT TOP 1 TABLE_NAME FROM INFORMATION_SCHEMA.TABLE_CONSTRAINTS WHERE constraint_catalog=DB_NAME() AND CONSTRAINT_TYPE = 'FOREIGN KEY' ORDER BY TABLE_NAME)
END
GO
/* Drop all Primary Key constraints */
DECLARE #name VARCHAR(128)
DECLARE #constraint VARCHAR(254)
DECLARE #SQL VARCHAR(254)
SELECT #name = (SELECT TOP 1 TABLE_NAME FROM INFORMATION_SCHEMA.TABLE_CONSTRAINTS WHERE constraint_catalog=DB_NAME() AND CONSTRAINT_TYPE = 'PRIMARY KEY' ORDER BY TABLE_NAME)
WHILE #name IS NOT NULL
BEGIN
SELECT #constraint = (SELECT TOP 1 CONSTRAINT_NAME FROM INFORMATION_SCHEMA.TABLE_CONSTRAINTS WHERE constraint_catalog=DB_NAME() AND CONSTRAINT_TYPE = 'PRIMARY KEY' AND TABLE_NAME = #name ORDER BY CONSTRAINT_NAME)
WHILE #constraint is not null
BEGIN
SELECT #SQL = 'ALTER TABLE [' + RTRIM(#name) +'] DROP CONSTRAINT ' + RTRIM(#constraint)
EXEC (#SQL)
PRINT 'Dropped PK Constraint: ' + #constraint + ' on ' + #name
SELECT #constraint = (SELECT TOP 1 CONSTRAINT_NAME FROM INFORMATION_SCHEMA.TABLE_CONSTRAINTS WHERE constraint_catalog=DB_NAME() AND CONSTRAINT_TYPE = 'PRIMARY KEY' AND CONSTRAINT_NAME <> #constraint AND TABLE_NAME = #name ORDER BY CONSTRAINT_NAME)
END
SELECT #name = (SELECT TOP 1 TABLE_NAME FROM INFORMATION_SCHEMA.TABLE_CONSTRAINTS WHERE constraint_catalog=DB_NAME() AND CONSTRAINT_TYPE = 'PRIMARY KEY' ORDER BY TABLE_NAME)
END
GO
/* Drop all tables */
DECLARE #name VARCHAR(128)
DECLARE #SQL VARCHAR(254)
SELECT #name = (SELECT TOP 1 [name] FROM sysobjects WHERE [type] = 'U' AND category = 0 ORDER BY [name])
WHILE #name IS NOT NULL
BEGIN
SELECT #SQL = 'DROP TABLE [' + RTRIM(#name) +']'
EXEC (#SQL)
PRINT 'Dropped Table: ' + #name
SELECT #name = (SELECT TOP 1 [name] FROM sysobjects WHERE [type] = 'U' AND category = 0 AND [name] > #name ORDER BY [name])
END
GO

You can try the open-source bsn ModuleStore versioning toolkit, which can create an inventory of a database and create a DROP script for a database schema which respects the dependencies of the objects. It currently supports tables, indexes, triggers, views, functions, stored procedures and XML schema collections.
using (ManagementConnectionProvider provider = new ManagementConnectionProvider(connection, "dbo")) {
DatabaseInventory inventory = new DatabaseInventory(provider, "dbo");
string dropScript = string.Join(";\r\nGO\r\n\r\n", inventory.GenerateUninstallSql().ToArray());
}

Select * From sysobjects Where....
Then drop one by one.

Related

Invalid Object Name - #temptable

This stored procedure creates a table in the database when I make the select * into, and because of that, when there is more than one user, an error appears and says SearchTMP table already exists, this happens even if I make a drop of that table. So I decided to make a temporary table, as the following code shows:
INSERT INTO #SQLTbl(Tablename, WHEREClause)
SELECT QUOTENAME(SCh.name) + '.' + QUOTENAME(ST.NAME),
(
SELECT '[' + SC.Name + ']' + ' LIKE ''' + REPLACE(SearchSTR.SearchString,'''','''''') + ''' OR ' + CHAR(10)
FROM SYS.columns SC
JOIN SYS.types STy
ON STy.system_type_id = SC.system_type_id
AND STy.user_type_id =SC.user_type_id
CROSS JOIN #SearchStringTbl SearchSTR
WHERE STY.name in ('varchar','char','nvarchar','nchar','text')
AND SC.object_id = ST.object_id
ORDER BY SC.name
FOR XML PATH('')
)
FROM SYS.tables ST
JOIN #CheckTableNames chktbls
ON chktbls.Tablename = ST.name
JOIN SYS.schemas SCh
ON ST.schema_id = SCh.schema_id
AND Sch.name = chktbls.Schemaname
WHERE ST.name <> '#MyTempTable' -- it was SearchTMP
GROUP BY ST.object_id, QUOTENAME(SCh.name) + '.' + QUOTENAME(ST.NAME);
UPDATE #SQLTbl SET SQLStatement = 'SELECT * INTO #MyTempTable FROM ' + Tablename + ' WHERE ' + substring(WHEREClause,1,len(WHEREClause)-5)
Since I didn't want to declare or create the table previously, the temptable will be created in the select * into. But when I try to run the procedure by filling the parameters it says:
>Msg 208, Level 16, State 0, Procedure SP_SearchTables_TEST, Line 265, Invalid object name #MyTempTable
The entire stored procedure:
ALTER PROCEDURE [dbo].[SearchTables_TEST] #SearchStr NVARCHAR(60) ,#GenerateSQLOnly Bit = 0 ,#SchemaNames VARCHAR(500) ='%' AS
SET NOCOUNT ON
DECLARE #MatchFound BIT
SELECT #MatchFound = 0
DECLARE #CheckTableNames Table
(
Schemaname sysname
,Tablename sysname
)
DECLARE #SearchStringTbl TABLE
(
SearchString VARCHAR(500)
)
DECLARE #SQLTbl TABLE
(
Tablename SYSNAME
,WHEREClause VARCHAR(MAX)
,SQLStatement VARCHAR(MAX)
,Execstatus BIT
)
DECLARE #SQL VARCHAR(MAX)
DECLARE #TableParamSQL VARCHAR(MAX)
DECLARE #SchemaParamSQL VARCHAR(MAX)
DECLARE #TblSQL VARCHAR(MAX)
DECLARE #tmpTblname sysname
DECLARE #ErrMsg VARCHAR(100)
IF LTRIM(RTRIM(#SchemaNames)) =''
BEGIN
SELECT #SchemaNames = '%'
END
IF CHARINDEX(',',#SchemaNames) > 0
SELECT #SchemaParamSQL = 'SELECT ''' + REPLACE(#SchemaNames,',','''as SchemaName UNION SELECT ''') + ''''
ELSE
SELECT #SchemaParamSQL = 'SELECT ''' + #SchemaNames + ''' as SchemaName '
SELECT #TblSQL = 'SELECT SCh.NAME,T.NAME
FROM SYS.TABLES T
JOIN SYS.SCHEMAS SCh
ON SCh.SCHEMA_ID = T.SCHEMA_ID
INNER JOIN [DynaForms].[dbo].[Enums_Tables] et on
(et.Id = T.NAME COLLATE Latin1_General_CI_AS) '
INSERT INTO #CheckTableNames
(Schemaname,Tablename)
EXEC(#TblSQL)
IF NOT EXISTS(SELECT 1 FROM #CheckTableNames)
BEGIN
SELECT #ErrMsg = 'No tables are found in this database ' + DB_NAME() + ' for the specified filter'
PRINT #ErrMsg
RETURN
END
IF LTRIM(RTRIM(#SearchStr)) =''
BEGIN
SELECT #ErrMsg = 'Please specify the search string in #SearchStr Parameter'
PRINT #ErrMsg
RETURN
END
ELSE
BEGIN
SELECT #SearchStr = REPLACE(#SearchStr,',,,',',#DOUBLECOMMA#')
SELECT #SearchStr = REPLACE(#SearchStr,',,','#DOUBLECOMMA#')
SELECT #SearchStr = REPLACE(#SearchStr,'''','''''')
SELECT #SQL = 'SELECT ''' + REPLACE(#SearchStr,',','''as SearchString UNION SELECT ''') + ''''
INSERT INTO #SearchStringTbl
(SearchString)
EXEC(#SQL)
UPDATE #SearchStringTbl
SET SearchString = REPLACE(SearchString ,'#DOUBLECOMMA#',',')
END
INSERT INTO #SQLTbl(Tablename,WHEREClause)
SELECT QUOTENAME(SCh.name) + '.' + QUOTENAME(ST.NAME),
(
SELECT '[' + SC.Name + ']' + ' LIKE ''' + REPLACE(SearchSTR.SearchString,'''','''''') + ''' OR ' + CHAR(10)
FROM SYS.columns SC
JOIN SYS.types STy
ON STy.system_type_id = SC.system_type_id
AND STy.user_type_id =SC.user_type_id
CROSS JOIN #SearchStringTbl SearchSTR
WHERE STY.name in ('varchar','char','nvarchar','nchar','text')
AND SC.object_id = ST.object_id
ORDER BY SC.name
FOR XML PATH('')
)
FROM SYS.tables ST
JOIN #CheckTableNames chktbls
ON chktbls.Tablename = ST.name
JOIN SYS.schemas SCh
ON ST.schema_id = SCh.schema_id
AND Sch.name = chktbls.Schemaname
WHERE ST.name <> '#MyTempTable' -- it was SearchTMP
GROUP BY ST.object_id, QUOTENAME(SCh.name) + '.' + QUOTENAME(ST.NAME);
UPDATE #SQLTbl SET SQLStatement = 'SELECT * INTO #MyTempTable FROM ' + Tablename + ' WHERE ' + substring(WHEREClause,1,len(WHEREClause)-5)
DELETE FROM #SQLTbl
WHERE WHEREClause IS NULL
DECLARE #output TABLE (Id VARCHAR(50), Name VARCHAR(100))
WHILE EXISTS (SELECT 1 FROM #SQLTbl WHERE ISNULL(Execstatus ,0) = 0)
BEGIN
SELECT TOP 1 #tmpTblname = Tablename , #SQL = SQLStatement
FROM #SQLTbl
WHERE ISNULL(Execstatus ,0) = 0
IF #GenerateSQLOnly = 0
BEGIN
IF OBJECT_ID('#MyTempTable','U') IS NOT NULL -- this line was uncomment
DROP TABLE #MyTempTable -- this line was uncomment
EXEC (#SQL)
IF EXISTS(SELECT 1 FROM #MyTempTable) -- It was like this: SearchTMP
BEGIN
SELECT #MatchFound = 1
INSERT INTO #output (Id, Name)
Select * from [DynaForms].[dbo].[Enums_Tables] where id in (SELECT parsename(#tmpTblname,1) FROM #MyTempTable) -- It was like this: SearchTMP
END
END
ELSE
BEGIN
PRINT REPLICATE('-',100)
PRINT #tmpTblname
PRINT REPLICATE('-',100)
PRINT replace(#SQL,'INTO #MyTempTable','')
END
UPDATE #SQLTbl
SET Execstatus = 1
WHERE Tablename = #tmpTblname
END
SELECT * FROM #output
IF #MatchFound = 0
BEGIN
SELECT #ErrMsg = 'No Matches are found in this database ' + DB_NAME() + ' for the specified filter'
PRINT #ErrMsg
RETURN
END
SET NOCOUNT OFF
OK, so a quick test actually answered this, and i can't believe I missed this (/facepalm). you can't use a INTO clause with dynamic SQL and a Temporary table and reference it afterwards; you need to CREATE the table. Consider the following:
DECLARE #SQL varchar(max);
SET #SQL = 'SELECT 1 AS A, 2 AS B INTO #test;';
EXEC (#SQL);
SELECT *
FROM #test;
DROP TABLE #test;
This returns the error:
Msg 208, Level 16, State 0, Line 5
Invalid object name '#test'.
And now, for the correct way:
DECLARE #SQL varchar(max);
CREATE TABLE #test (A int, B int);
SET #SQL = 'INSERT INTO #test SELECT 1 AS A, 2 AS B';
EXEC (#SQL);
SELECT *
FROM #test;
DROP TABLE #test;
This works fine. Thus, you need to CREATE your temporary table, not use an INTO clause.
Instead of
Object_Id('#MyTempTable','U')
You need to use
Object_Id('tempdb..#MyTempTable','U')
To get the object_id of the temporary table to check if it exists or not.
Temp tables are created in TempDB system database

Temp Table - Temporary table is empty - SQL Server

I know this question I'm about to ask is quite common, but I haven't been able to use other examples to my own.
I have a stored procedure that uses a table Enum_Tables (this table has other table names) to search the entire database for a specific string. The results are stored in a table which gives me the specific rows of Enum_Tables that I want.
Currently the stored is working properly, but right now it is creating SearchTMP in the Database. And I don't want that, What I want is creating a temporary table like #SearchTMP. I created the temporary table, I tried to populated it, but It is empty.
The part I'm talking about is inside the while logic (WHILE EXISTS (SELECT 1 FROM #SQLTbl WHERE ISNULL(Execstatus ,0) = 0) ).
It's checking if there is values in SearchTMP, and since it's not a temporary table, it's creating one in the database. I want to change it to a #SearchTMP. I I created the table, but I'm not being able to populated it, since I wan't being able to do it, I deleted that code. I know I need to do an insert, but how can I do it without changing to much code, and maintain the same logic.
This is my stored procedure code:
ALTER PROCEDURE [dbo].[SearchTables_TEST]
--#Tablenames VARCHAR(500)
#SearchStr NVARCHAR(60),
#GenerateSQLOnly Bit = 0,
#SchemaNames VARCHAR(500) ='%'
AS
SET NOCOUNT ON
DECLARE #MatchFound BIT
SELECT #MatchFound = 0
DECLARE #CheckTableNames Table (Schemaname sysname, Tablename sysname)
DECLARE #SearchStringTbl TABLE (SearchString VARCHAR(500))
DECLARE #SQLTbl TABLE (Tablename SYSNAME,
WHEREClause VARCHAR(MAX),
SQLStatement VARCHAR(MAX),
Execstatus BIT
)
DECLARE #SQL VARCHAR(MAX)
DECLARE #TableParamSQL VARCHAR(MAX)
DECLARE #SchemaParamSQL VARCHAR(MAX)
DECLARE #TblSQL VARCHAR(MAX)
DECLARE #tmpTblname sysname
DECLARE #ErrMsg VARCHAR(100)
IF LTRIM(RTRIM(#SchemaNames)) =''
BEGIN
SELECT #SchemaNames = '%'
END
--IF CHARINDEX(',',#Tablenames) > 0
-- SELECT #TableParamSQL = 'SELECT ''' + REPLACE(#Tablenames,',','''as TblName UNION SELECT ''') + ''''
--ELSE
-- SELECT #TableParamSQL = 'SELECT ''' + #Tablenames + ''' as TblName '
IF CHARINDEX(',',#SchemaNames) > 0
SELECT #SchemaParamSQL = 'SELECT ''' + REPLACE(#SchemaNames,',','''as SchemaName UNION SELECT ''') + ''''
ELSE
SELECT #SchemaParamSQL = 'SELECT ''' + #SchemaNames + ''' as SchemaName '
SELECT #TblSQL = 'SELECT SCh.NAME,T.NAME
FROM SYS.TABLES T
JOIN SYS.SCHEMAS SCh
ON SCh.SCHEMA_ID = T.SCHEMA_ID
INNER JOIN [DynaForms].[dbo].[Enums_Tables] et on
(et.Id = T.NAME COLLATE Latin1_General_CI_AS) '
INSERT INTO #CheckTableNames
(Schemaname,Tablename)
EXEC(#TblSQL)
IF NOT EXISTS(SELECT 1 FROM #CheckTableNames)
BEGIN
SELECT #ErrMsg = 'No tables are found in this database ' + DB_NAME() + ' for the specified filter'
PRINT #ErrMsg
RETURN
END
IF LTRIM(RTRIM(#SearchStr)) =''
BEGIN
SELECT #ErrMsg = 'Please specify the search string in #SearchStr Parameter'
PRINT #ErrMsg
RETURN
END
ELSE
BEGIN
SELECT #SearchStr = REPLACE(#SearchStr,',,,',',#DOUBLECOMMA#')
SELECT #SearchStr = REPLACE(#SearchStr,',,','#DOUBLECOMMA#')
SELECT #SearchStr = REPLACE(#SearchStr,'''','''''')
SELECT #SQL = 'SELECT ''' + REPLACE(#SearchStr,',','''as SearchString UNION SELECT ''') + ''''
INSERT INTO #SearchStringTbl
(SearchString)
EXEC(#SQL)
UPDATE #SearchStringTbl
SET SearchString = REPLACE(SearchString ,'#DOUBLECOMMA#',',')
END
INSERT INTO #SQLTbl
( Tablename,WHEREClause)
SELECT QUOTENAME(SCh.name) + '.' + QUOTENAME(ST.NAME),
(
SELECT '[' + SC.Name + ']' + ' LIKE ''' + REPLACE(SearchSTR.SearchString,'''','''''') + ''' OR ' + CHAR(10)
FROM SYS.columns SC
JOIN SYS.types STy
ON STy.system_type_id = SC.system_type_id
AND STy.user_type_id =SC.user_type_id
CROSS JOIN #SearchStringTbl SearchSTR
WHERE STY.name in ('varchar','char','nvarchar','nchar','text')
AND SC.object_id = ST.object_id
ORDER BY SC.name
FOR XML PATH('')
)
FROM SYS.tables ST
JOIN #CheckTableNames chktbls
ON chktbls.Tablename = ST.name
JOIN SYS.schemas SCh
ON ST.schema_id = SCh.schema_id
AND Sch.name = chktbls.Schemaname
WHERE ST.name <> 'SearchTMP'
GROUP BY ST.object_id, QUOTENAME(SCh.name) + '.' + QUOTENAME(ST.NAME) ;
UPDATE #SQLTbl SET SQLStatement = 'SELECT * INTO SearchTMP FROM ' + Tablename + ' WHERE ' + substring(WHEREClause,1,len(WHEREClause)-5) -- this line was uncomment
DELETE FROM #SQLTbl
WHERE WHEREClause IS NULL
DECLARE #output TABLE (Id VARCHAR(50), Name VARCHAR(100))
Create Table #SearchTMP (searchparameter varchar(200))
WHILE EXISTS (SELECT 1 FROM #SQLTbl WHERE ISNULL(Execstatus ,0) = 0)
BEGIN
SELECT TOP 1 #tmpTblname = Tablename , #SQL = SQLStatement
FROM #SQLTbl
WHERE ISNULL(Execstatus ,0) = 0
IF #GenerateSQLOnly = 0
BEGIN
IF OBJECT_ID('SearchTMP','U') IS NOT NULL -- this line was uncomment
DROP TABLE SearchTMP -- this line was uncomment
EXEC (#SQL)
IF EXISTS(SELECT 1 FROM SearchTMP)
BEGIN
--SELECT parsename(#tmpTblname,1) FROM SearchTMP
SELECT #MatchFound = 1
INSERT INTO #output (Id, Name)
Select * from [DynaForms].[dbo].[Enums_Tables] where id in (SELECT parsename(#tmpTblname,1) FROM SearchTMP)
END
END
ELSE
BEGIN
PRINT REPLICATE('-',100)
PRINT #tmpTblname
PRINT REPLICATE('-',100)
PRINT replace(#SQL,'INTO SearchTMP','')
END
UPDATE #SQLTbl
SET Execstatus = 1
WHERE Tablename = #tmpTblname
END
SELECT * FROM #output
IF #MatchFound = 0
BEGIN
SELECT #ErrMsg = 'No Matches are found in this database ' + DB_NAME() + ' for the specified filter'
PRINT #ErrMsg
RETURN
END
SET NOCOUNT OFF
When you want to use a temp table in a dynamic query, you have to create said temp table first, then populate it in the dynamic query.
CREATE TABLE #MyTempTable (ID INT NOT NULL);
DECLARE #STMT NVARCHAR(MAX) = N'INSERT INTO #MyTempTable (ID) SELECT ID FROM MyTable;';
EXEC sp_executesql
#stmt = #STMT
;
SELECT ID FROM #MyTempTable;
Since the temp table is created in the stored procedure, it is scoped to that stored procedure and will be dropped automatically when the SP finishes.
If you want to use said temp table outside of the SP, you have to create it outside of the SP. (If it is part of the batch, the temp table will be dropped when the connection is closed or you can drop it explicitly).

SQL Server : select columns of a table then select top 1 value

Is there a way to select columns of a table then assign the top 1 value of that column.
For example
TABLENAME | COLUMNNAME | VALUE
----------+------------+---------------
TABLE 1 | COLUMN 1 | COLUMN 1 VALUE
TABLE 1 | COLUMN 2 | COLUMN 2 VALUE
UPDATE
DECLARE #tableCOLS TABLE (tablename varchar(255) , colname varchar(255));
BEGIN
SET #MyCursor = CURSOR FOR
SELECT DISTINCT tablename FROM #tableid
OPEN #MyCursor
FETCH NEXT FROM #MyCursor
INTO #MyField2
WHILE ##FETCH_STATUS = 0
BEGIN
INSERT INTO #tableCOLS
SELECT #MyField2 , COLUMN_NAME
FROM INFORMATION_SCHEMA.COLUMNS
WHERE TABLE_NAME = #MyField2
FETCH NEXT FROM #MyCursor
INTO #MyField2
END;
CLOSE #MyCursor ;
DEALLOCATE #MyCursor;
END;
SELECT * from #tableCOLS
END;
I fetch the table columns to my dynamic table then i want to insert the value of a certain data in the columns that i fetch in my table
I just tested this and it works a treat
DECLARE #Result TABLE (TableName VARCHAR(50), Col VARCHAR(50), MaxValue VARCHAR(50), MaxSQL NVARCHAR(4000));
DECLARE #TableName VARCHAR(50), #Col VARCHAR(50), #MaxSQL NVARCHAR(4000), #MaxValue VARCHAR(50)
-- Load all tables and columns of interest
INSERT INTO #Result
(TableName, Col, MaxSQL)
select
object_name(object_id),
name,
'SELECT #C = MAX(' + name + ') FROM ' + object_name(object_id)
from sys.columns where object_name(object_id) = 'Table1'
-- For each row, run the dynamic SQL and update back into table
DECLARE c CURSOR FOR
SELECT TableName, Col, MaxSQL FROM #Result
OPEN c
FETCH NEXT FROM C INTO #TableName, #Col, #MaxSQL
WHILE ##FETCH_STATUS = 0
BEGIN
EXEC sp_ExecuteSQL #MaxSQL, N'#C VARCHAR(50) OUTPUT', #C = #MaxValue OUTPUT
UPDATE #Result SET MaxValue = #MaxValue WHERE TableName = #TableName AND Col = #Col;
FETCH NEXT FROM C INTO #TableName, #Col, #MaxSQL
END
CLOSE c;
DEALLOCATE c;
-- Show the results
SELECT * FROM #Result;
There's no need to use loops or cursors to do this. Have a look at the following...
SET NOCOUNT ON;
DECLARE #Object_id INT = OBJECT_ID('DataBaseName.Schema.TableName');
IF OBJECT_ID('tempdb..#TableCols', 'U') IS NOT NULL
DROP TABLE #TableCols;
CREATE TABLE #TableCols (
SchemaName sysname,
TableName sysname,
ColumnName sysname,
ColumnID INT NOT NULL,
Value NVARCHAR(MAX) NULL
);
INSERT #TableCols (SchemaName, TableName, ColumnName, ColumnID)
SELECT
s.name,
o.name,
c.name,
c.column_id
FROM
sys.objects o
JOIN sys.schemas s
ON o.schema_id = s.schema_id
JOIN sys.columns c
ON o.object_id = c.object_id
WHERE
o.type = 'U'
AND o.object_id = #Object_id
ORDER BY
c.column_id;
DECLARE
#CrossCols VARCHAR(MAX) = N'',
#TopVal NVARCHAR(10) = N'',
#Table sysname = N'',
#sql NVARCHAR(MAX) = N'',
#DeBug BIT = 0; -- 1 = PRINT ; 0 = EXECUTE
SELECT
#CrossCols = CONCAT(#CrossCols, N',
(', tc.ColumnID, N', CAST(t.[', tc.ColumnName, N'] AS NVARCHAR(MAX)))'),
#TopVal = tc.ColumnID,
#Table = CONCAT(tc.SchemaName, '.', tc.TableName)
FROM
#TableCols tc
ORDER BY
tc.ColumnID;
SET #sql = CONCAT(N'
UPDATE tc SET
tc.Value = t.ColumnValue
FROM
#TableCols tc
JOIN (
SELECT TOP (', #TopVal, N')
x.*
FROM
', #Table, N' t
CROSS APPLY ( VALUES', STUFF(#CrossCols, 1, 1, ''), N'
) x (ColumnID, ColumnValue)
) t
ON tc.ColumnID = t.ColumnID;')
IF #DeBug = 1
BEGIN
EXEC dbo.LongPrint #sql;
END;
ELSE
BEGIN
EXEC(#sql);
SELECT * FROM #TableCols tc;
END;
Give this a shot...
DECLARE #Table VARCHAR(MAX) = 'Customer'
SELECT t.name AS [Table]
, c.name AS [Column]
, cmd.mycmd
, TYPE_NAME(c.user_type_id) AS [Type]
, c.max_length AS [Size]
, CASE WHEN c.is_nullable = 1 THEN ''
ELSE 'No Nulls' END AS Nullable
, ROW_NUMBER() OVER ( PARTITION BY t.name ORDER BY c.name ASC ) AS rnk
, CASE WHEN EXISTS ( SELECT 1
FROM sys.columns c2
WHERE c2.object_id = t.object_id
AND c2.name IN ( SELECT *
FROM dbo.fnSplit('Fieldnames,ToSkip', ',') ) ) THEN 'Y'
ELSE 'N' END AS [CreModDeLs]
into #MyTempTable
FROM sys.columns AS c
JOIN sys.tables AS t ON c.object_id = t.object_id
cross apply (Select 'Select top 1 #Val = cast(' + c.name + ' as varchar(max)) from ' + t.name + ' Order by 1 desc' as mycmd) cmd
WHERE t.name LIKE #Table
ORDER BY t.name
, c.name
alter table #MyTempTable add [Id] integer identity(1,1)
alter table #MyTempTable add [Top1Val] Varchar(max)
Declare #DynamicSQL as nvarchar(1000);
Declare #dynamicparamdec nvarchar(1000) = '#val Varchar(max) Output'
Declare #valueofid as int
Declare #returnval as varchar(max)
Declare #Id integer
DECLARE #MyCursor CURSOR FAST_FORWARD
FOR
SELECT id
, mycmd
FROM #MyTempTable
where type <> 'image'
OPEN #MyCursor
FETCH #MyCursor INTO #id, #DynamicSQL
WHILE ##fetch_status = 0
BEGIN
print #dynamicsql
execute sp_executesql #DynamicSQL
, #dynamicparamdec
, #returnval output
update #MyTempTable
set Top1Val = #returnval
where id = #id
FETCH #MyCursor INTO #id, #DynamicSQL
END
--Close the cursor, if it is empty then deallocate it:
IF ( SELECT CURSOR_STATUS('global', '#MyCursor') ) >= -1
BEGIN
IF ( SELECT CURSOR_STATUS('global', '#MyCursor') ) > -1
BEGIN
CLOSE #MyCursor
END
DEALLOCATE #MyCursor
END
select * from #MyTempTable

How to change column from one data type to antother using script

I must change for lots of tables 30+ one column's data type from Int to BigInt.
My problem is that particular column is also for one table the PK and for lots others the FK. Therefore I cannot change as I got error message.
I need an algorithm, or some script. But I cannot figure the steps, or the approach: should I use a currsor, or just a temp table from which to delete a record and always to get the first one...
And what should I do? Take first table from the stack, check if the column in question is referenced either by PK or FK, if so drop the references (PK, FK, etc) then alter the column type, then recreate the Pk and the FKs? Should I store what I have doped? I'm very confused...
Any hints?
One option would be to not delete records if you have a lot, think instead about adding another column to each table which is of BigInt datatype and then move the data from your primary key column to this new column.
ALTER TABLE Table1 ADD COLUMN NewPKColumn BigInt;
UPDATE Table1 SET NewPkColumn = CurrentPKColumn;
You do the same with the other tables which reference this new BigInt column, you add a new column of datatype BigInt, move the data.
ALTER TABLE Table2 ADD COLUMN NewPKColumn_FK BigInt;
UPDATE Table2 SET NewPKColumn_FK = Current_FK_Column;
(repeat this for all tables...)
When you've done this for all tables you can remove the PK from the original PK column and drop that column (but before this, make sure you take a look and see what type of indexes is created on the PK column - clustered or non-clustered) and also, don't forget to create the FK's again.
ALTER TABLE Table2 DROP CONSTRAINT FK_Tbl1;
ALTER TABLE Table1 DROP COLUMN CurrentPKColumn;
ALTER TABLE Table2 ADD CONSTRAINT FK_Tbl1 REFERENCES Table1(NewPKColumn);
Also, you'll need to look over what indexes exist and include the current PK column as you'll need to recreate those as well.
And, as always, first test this on a development environment to make sure you haven't skipped anything.
Ok, this is going to be a beast of a script but I'm working through the same issue at the moment. This script is still a work in progress but should help you with what you'll need to do.
My current code uses a given table and field, feel free to edit;
DECLARE #TableToEdit varchar(255); SET #TableToEdit = 'Entity'
DECLARE #MasterField sysname; SET #MasterField = 'Entity_Identifier'
You're going to need to drop all foreign keys first;
IF OBJECT_ID('tempdb..#ForeignKeys') IS NOT NULL
DROP TABLE #ForeignKeys
CREATE TABLE #ForeignKeys
(
PKTABLE_QUALIFIER nvarchar(255) NULL
,PKTABLE_OWNER nvarchar(255) NULL
,PKTABLE_NAME nvarchar(255) NULL
,PKCOLUMN_NAME varchar(255) NULL
,FKTABLE_QUALIFIER nvarchar(255) NULL
,FKTABLE_OWNER nvarchar(255) NULL
,FKTABLE_NAME nvarchar(255) NULL
,FKCOLUMN_NAME nvarchar(255) NULL
,KEY_SQL int NULL
,UPDATE_RULE int NULL
,DELETE_RULE int NULL
,FK_NAME nvarchar(255) NULL
,PK_NAME nvarchar(255) NULL
,DEFERRABILITY int NULL
)
/* find all tables that have an Entity_Identifier field that's not already an int */
IF OBJECT_ID('tempdb..#MasterTables') IS NOT NULL DROP TABLE #MasterTables
CREATE TABLE #MasterTables (MasterTableName sysname, MasterTableSQL nvarchar(max))
INSERT INTO #MasterTables (MasterTableName, MasterTableSQL)
SELECT DISTINCT
o.name TableName
,'INSERT INTO #ForeignKeys EXEC sp_fkeys ' + o.name MasterTableSQL
FROM sys.objects o
JOIN sys.columns c
ON o.object_id = c.object_id
JOIN sys.types t
ON c.user_type_id = t.user_type_id
WHERE o.type = 'u'
--AND t.name NOT IN ('int','bigint')
--AND c.name LIKE '%Entity_Identifier%'
AND c.name LIKE '%' + #MasterField + '%'
/* Let's find all Foreign Keys based upon a table that has an Entity_Identifier field that needs to be converted */
DECLARE #execspfkeys nvarchar(max)
DECLARE spfkeyscursor CURSOR LOCAL FOR
SELECT MasterTableSQL FROM #MasterTables
OPEN spfkeyscursor
FETCH NEXT FROM spfkeyscursor INTO #execspfkeys
WHILE ##FETCH_STATUS = 0 BEGIN
--execute your sproc on each row
EXEC sp_executesql #execspfkeys
FETCH NEXT FROM spfkeyscursor INTO #execspfkeys
END
CLOSE spfkeyscursor
DEALLOCATE spfkeyscursor
/* Ok, let's get the foreign key definitions from all relevant tables */
IF OBJECT_ID('tempdb..#FKScripts') IS NOT NULL
DROP TABLE #FKScripts
CREATE TABLE #FKScripts
(
FKName nvarchar(255)
,FKTableName nvarchar(255)
,FKSchema nvarchar(10)
,FKDatabase nvarchar(255)
,PKName nvarchar(255)
,PKTableName nvarchar(255)
,PKSchema nvarchar(10)
,PKDatabase nvarchar(255)
,FKDisableScript nvarchar(max)
,FKRebuildScript nvarchar(max)
,FKCheckScript nvarchar(max)
)
INSERT INTO #FKScripts (FKName, FKTableName, FKSchema, FKDatabase, PKName, PKTableName, PKSchema, PKDatabase, FKDisableScript, FKRebuildScript, FKCheckScript)
SELECT DISTINCT
fk.FK_NAME
,fk.FKTABLE_NAME
,fk.FKTABLE_OWNER
,fk.FKTABLE_QUALIFIER
,fk.PK_NAME
,fk.PKTABLE_NAME
,fk.PKTABLE_OWNER
,fk.PKTABLE_QUALIFIER
,'ALTER TABLE [' + fk.FKTABLE_OWNER + '].[' + fk.FKTABLE_NAME + '] DROP CONSTRAINT [' + fk.FK_NAME + ']' FKDisableScript
,'ALTER TABLE [' + fk.FKTABLE_OWNER + '].[' + fk.FKTABLE_NAME + '] WITH CHECK ADD CONSTRAINT [' + fk.FK_NAME + '] FOREIGN KEY (' + PKList.FieldList +') REFERENCES [dbo].[' + fk.PKTABLE_NAME + '] (' + FKlist.FieldList + ')' FKRebuildScript
,'ALTER TABLE [' + fk.FKTABLE_OWNER + '].[' + fk.FKTABLE_NAME + '] CHECK CONSTRAINT [' + fk.FK_NAME + ']' FKCheckScript
FROM #ForeignKeys fk
INNER JOIN
(
SELECT DISTINCT
fk.FK_NAME,
STUFF((SELECT ','+ fk2.PKCOLUMN_NAME
FROM (SELECT FK_NAME, '[' + PKCOLUMN_NAME +']' PKCOLUMN_NAME FROM #ForeignKeys) fk2
WHERE FK.FK_NAME = fk2.FK_NAME
GROUP BY fk2.PKCOLUMN_NAME
FOR XML PATH(''), TYPE).value('.','VARCHAR(max)'), 1, 1, '') FieldList
FROM #ForeignKeys fk
) PKlist
ON fk.FK_NAME = PKlist.FK_NAME
INNER JOIN
(
SELECT DISTINCT
fk.FK_NAME,
STUFF((SELECT ','+ fk2.FKCOLUMN_NAME
FROM (SELECT FK_NAME, '[' + FKCOLUMN_NAME + ']' FKCOLUMN_NAME FROM #ForeignKeys) fk2
WHERE FK.FK_NAME = fk2.FK_NAME
GROUP BY fk2.FKCOLUMN_NAME
FOR XML PATH(''), TYPE).value('.','VARCHAR(max)'), 1, 1, '') FieldList
FROM #ForeignKeys fk
) FKlist
ON fk.FK_NAME = FKlist.FK_NAME
DROP TABLE #ForeignKeys
SELECT * FROM #FKScripts
/* OK, let's disable these foreign keys, going to have to use a cursor for this (ouch) */
DECLARE #disablesql nvarchar(max)
DECLARE discur CURSOR LOCAL FOR
SELECT FKDisableScript FROM #FKScripts
OPEN discur
FETCH NEXT FROM discur INTO #disablesql
WHILE ##FETCH_STATUS = 0 BEGIN
--execute your sproc on each row
EXEC sp_executesql #disablesql
FETCH NEXT FROM discur INTO #disablesql
END
CLOSE discur
DEALLOCATE discur
/* right, we're finished with the cursor that disables the foreign keys, phew! */
/* check that the constraints are now disabled (for testing) */
SELECT DISTINCT
fkt.*
,CASE WHEN ((C.Status & 0x4000)) = 0 THEN 1 ELSE 0 END [Enabled2]
FROM #FKScripts fkt
INNER JOIN sys.sysobjects o2
ON o2.name = fkt.FKName
INNER JOIN sys.sysobjects o
ON o2.id = o.parent_obj
AND o.xtype='F'
INNER JOIN sys.sysconstraints c
ON o.id = c.constid
select * from #FKScripts
Then you're going to need to drop all indexes;
/* Drop index scripts into a temp table */
IF OBJECT_ID('tempdb..#CreateIndexes') IS NOT NULL DROP TABLE #CreateIndexes
GO
DECLARE #SchemaName varchar(100)
DECLARE #TableName varchar(256)
DECLARE #IndexName varchar(256)
DECLARE #ColumnName varchar(100)
DECLARE #is_unique varchar(100)
DECLARE #IndexTypeDesc varchar(100)
DECLARE #FileGroupName varchar(100)
DECLARE #is_disabled bit
DECLARE #is_primary_key bit
DECLARE #IndexOptions varchar(max)
DECLARE #IndexColumnId int
DECLARE #IsDescendingKey int
DECLARE #IsIncludedColumn int
DECLARE #TSQLScripCreationIndex varchar(max)
DECLARE #TSQLScripDisableIndex varchar(max)
CREATE TABLE #CreateIndexes (
SchemaName varchar(max)
,TableName varchar(max)
,IndexName varchar(max)
,is_unique varchar(max)
,IndexTypeDesc varchar(max)
,is_disabled bit
,is_primary_key bit
,FileGroupName varchar(max)
,DropScript varchar(max)
,TSQLScripCreationIndex varchar(max)
,TSQLScripDisableIndex varchar(max)
)
DECLARE CursorIndex CURSOR FOR
SELECT schema_name(t.schema_id) [schema_name]
, t.name
, ix.name
, CASE WHEN ix.is_unique = 1 THEN 'UNIQUE ' ELSE '' END
, ix.type_desc
, '' IndexOptions -- case when ix.is_padded=1 then 'PAD_INDEX = ON, ' else 'PAD_INDEX = OFF, ' end
--+ case when ix.allow_page_locks=1 then 'ALLOW_PAGE_LOCKS = ON, ' else 'ALLOW_PAGE_LOCKS = OFF, ' end
--+ case when ix.allow_row_locks=1 then 'ALLOW_ROW_LOCKS = ON, ' else 'ALLOW_ROW_LOCKS = OFF, ' end
--+ case when INDEXPROPERTY(t.object_id, ix.name, 'IsStatistics') = 1 then 'STATISTICS_NORECOMPUTE = ON, ' else 'STATISTICS_NORECOMPUTE = OFF, ' end
--+ case when ix.ignore_dup_key=1 then 'IGNORE_DUP_KEY = ON, ' else 'IGNORE_DUP_KEY = OFF, ' end
--+ 'SORT_IN_TEMPDB = OFF, FILLFACTOR = ' + CASE WHEN ix.fill_factor = 0 THEN '90' ELSE CAST(ix.fill_factor AS VARCHAR(3)) END AS IndexOptions
, ix.is_disabled
, ix.is_primary_key
, FILEGROUP_NAME(ix.data_space_id) FileGroupName
FROM sys.tables t
INNER JOIN sys.indexes ix on t.object_id=ix.object_id
INNER JOIN #FKScripts fks ON t.name = fks.FKTableName
WHERE ix.type>0
AND t.is_ms_shipped=0
AND t.name<>'sysdiagrams'
--and t.name = 'Entity'
ORDER BY schema_name(t.schema_id), t.name, ix.name
OPEN CursorIndex
FETCH NEXT FROM CursorIndex INTO #SchemaName, #TableName, #IndexName, #is_unique, #IndexTypeDesc, #IndexOptions,#is_disabled, #is_primary_key, #FileGroupName
WHILE (##fetch_status=0)
BEGIN
DECLARE #IndexColumns varchar(max)
DECLARE #IncludedColumns varchar(max)
SET #IndexColumns=''
SET #IncludedColumns=''
DECLARE CursorIndexColumn CURSOR FOR
SELECT
col.name
,ixc.is_descending_key
,ixc.is_included_column
FROM sys.tables tb
INNER JOIN sys.indexes ix
ON tb.object_id=ix.object_id
INNER JOIN sys.index_columns ixc
ON ix.object_id=ixc.object_id
AND ix.index_id= ixc.index_id
INNER JOIN sys.columns col
ON ixc.object_id = col.object_id
AND ixc.column_id = col.column_id
WHERE ix.type>0
AND (ix.is_primary_key=0 or ix.is_unique_constraint=0)
AND schema_name(tb.schema_id) = #SchemaName
AND tb.name = #TableName
AND ix.name = #IndexName
ORDER BY ixc.index_column_id
OPEN CursorIndexColumn
FETCH NEXT FROM CursorIndexColumn INTO #ColumnName, #IsDescendingKey, #IsIncludedColumn
WHILE (##fetch_status=0)
BEGIN
IF #IsIncludedColumn=0
SET #IndexColumns=#IndexColumns + #ColumnName + CASE WHEN #IsDescendingKey=1 THEN ' DESC, ' ELSE ' ASC, ' END
ELSE
SET #IncludedColumns=#IncludedColumns + #ColumnName +', '
FETCH NEXT FROM CursorIndexColumn INTO #ColumnName, #IsDescendingKey, #IsIncludedColumn
END
CLOSE CursorIndexColumn
DEALLOCATE CursorIndexColumn
SET #IndexColumns = substring(#IndexColumns, 1, len(#IndexColumns)-1)
SET #IncludedColumns = CASE WHEN len(#IncludedColumns) >0 THEN substring(#IncludedColumns, 1, len(#IncludedColumns)-1) ELSE '' END
-- print #IndexColumns
-- print #IncludedColumns
SET #TSQLScripCreationIndex =''
SET #TSQLScripDisableIndex =''
SET #TSQLScripCreationIndex=
CASE WHEN #is_primary_key = 1 THEN 'ALTER TABLE ' + QUOTENAME(#SchemaName) +'.'+ QUOTENAME(#TableName) + ' ADD CONSTRAINT ' + QUOTENAME(#IndexName) + ' PRIMARY KEY CLUSTERED (' + #IndexColumns + ' )' + #IndexOptions + ' ON ' + QUOTENAME(#FileGroupName) + ';'
ELSE 'CREATE '+ #is_unique +#IndexTypeDesc + ' INDEX ' +QUOTENAME(#IndexName)+' ON ' + QUOTENAME(#SchemaName) +'.'+ QUOTENAME(#TableName)+ ' ('+#IndexColumns+') '
+ CASE WHEN len(#IncludedColumns)>0 THEN 'INCLUDE (' + #IncludedColumns+ ')' ELSE '' END + CHAR(13) --+'WITH (' + #IndexOptions+ ') ON ' + QUOTENAME(#FileGroupName) + ';'
END
--if #is_disabled=1
SET #TSQLScripDisableIndex= CASE WHEN #IndexTypeDesc = 'CLUSTERED' THEN 'ALTER TABLE ' + QUOTENAME(#SchemaName) +'.'+ QUOTENAME(#TableName) + ' DROP CONSTRAINT ' + QUOTENAME(#IndexName)
ELSE 'DROP INDEX ' + QUOTENAME(#IndexName) + ' ON ' + QUOTENAME(#SchemaName) +'.'+ QUOTENAME(#TableName) + CHAR(13) END
PRINT #TSQLScripCreationIndex
PRINT #TSQLScripDisableIndex
INSERT INTO #CreateIndexes (SchemaName, TableName, IndexName, is_unique, IndexTypeDesc, is_disabled, is_primary_key ,FileGroupName, TSQLScripCreationIndex, TSQLScripDisableIndex)
SELECT #SchemaName, #TableName, #IndexName, #is_unique, #IndexTypeDesc, #is_disabled, #is_primary_key, #FileGroupName, #TSQLScripCreationIndex, #TSQLScripDisableIndex
FETCH NEXT FROM CursorIndex INTO #SchemaName, #TableName, #IndexName, #is_unique, #IndexTypeDesc, #IndexOptions,#is_disabled, #is_primary_key ,#FileGroupName
END
CLOSE CursorIndex
DEALLOCATE CursorIndex
SELECT * FROM #CreateIndexes ORDER BY TableName, IndexName
If you've got full text indexes then you'll need this;
/* NEED TO DISABLE FULL TEXT INDEXES ON ANY OF THESE TABLES - AAARRRGGGGGHHHHHH!!!! */
IF OBJECT_ID('tempdb..#FullTextCreateScripts') IS NOT NULL DROP TABLE #FullTextCreateScripts
CREATE TABLE #FullTextCreateScripts (TableName sysname, ColumnName sysname, FullTextCreateScript nvarchar(max))
INSERT INTO #FullTextCreateScripts (TableName, ColumnName, FullTextCreateScript)
SELECT
o.name TableName
,c.name ColumnName
,'ADD FULLTEXT INDEX ON ' + o.name + 'ADD (' + c.name + ')' FullTextCreateScript
FROM sys.fulltext_index_columns fic
LEFT JOIN sys.objects o
ON o.object_id = fic.object_id
LEFT JOIN sys.columns c
ON c.object_id = fic.object_id
AND c.column_id = fic.column_id
INNER JOIN #FKScripts fks
ON o.name = fks.FKTableName
SELECT * FROM #FullTextCreateScripts
IF OBJECT_ID('tempdb..#FullTextDropScripts') IS NOT NULL DROP TABLE #FullTextDropScripts
CREATE TABLE #FullTextDropScripts (TableName sysname, FullTextDropScript nvarchar(max))
INSERT INTO #FullTextDropScripts (TableName, FullTextDropScript)
SELECT DISTINCT
o.name TableName
,'DROP FULLTEXT INDEX ON ' + o.name FullTextDropScript
FROM sys.fulltext_index_columns fic
LEFT JOIN sys.objects o
ON o.object_id = fic.object_id
INNER JOIN #FKScripts fks
ON o.name = fks.FKTableName
SELECT * FROM #FullTextDropScripts
/* Another cursor, this one drops our relevant full text indexes */
DECLARE #dropfulltextSQL nvarchar(max)
DECLARE dropfulltextcursor CURSOR LOCAL FOR
SELECT FullTextDropScript FROM #FullTextDropScripts
OPEN dropfulltextcursor
FETCH NEXT FROM dropfulltextcursor INTO #dropfulltextSQL
WHILE ##FETCH_STATUS = 0 BEGIN
--execute your sproc on each row
EXEC sp_executesql #dropfulltextSQL
FETCH NEXT FROM dropfulltextcursor INTO #dropfulltextSQL
END
CLOSE dropfulltextcursor
DEALLOCATE dropfulltextcursor
/* Let's drop those indexes using a cursor */
DECLARE #dropindexes nvarchar(max)
DECLARE dropindex CURSOR LOCAL FOR
SELECT TSQLScripDisableIndex FROM #CreateIndexes
OPEN dropindex
FETCH NEXT FROM dropindex INTO #dropindexes
WHILE ##FETCH_STATUS = 0 BEGIN
--execute your sproc on each row
EXEC sp_executesql #dropindexes
FETCH NEXT FROM dropindex INTO #dropindexes
END
CLOSE dropindex
DEALLOCATE dropindex
THIS IS WHERE YOU'LL WANT TO DO YOUR ALTER SCRIPT
Once you've done the alter, then start re-applying everything you've dropped;
/* Let's add those full text indexes back in */
DECLARE #addfulltextSQL nvarchar(max)
DECLARE createfulltextcursor CURSOR LOCAL FOR
SELECT FullTextCreateScript FROM #FullTextCreateScripts
OPEN createfulltextcursor
FETCH NEXT FROM createfulltextcursor INTO #addfulltextSQL
WHILE ##FETCH_STATUS = 0 BEGIN
--execute your sproc on each row
EXEC sp_executesql #addfulltextSQL
FETCH NEXT FROM createfulltextcursor INTO #addfulltextSQL
END
CLOSE createfulltextcursor
DEALLOCATE createfulltextcursor
/* Rebuild those indexes */
DECLARE #createindexes nvarchar(max)
DECLARE createindexes CURSOR LOCAL FOR
SELECT TSQLScripCreationIndex FROM #CreateIndexes
OPEN createindexes
FETCH NEXT FROM createindexes INTO #createindexes
WHILE ##FETCH_STATUS = 0 BEGIN
--execute your sproc on each row
EXEC sp_executesql #createindexes
FETCH NEXT FROM createindexes INTO #createindexes
END
CLOSE createindexes
DEALLOCATE createindexes
/* Now let's re-enable those FK constraints */
DECLARE #enablesql nvarchar(max)
DECLARE #checksql nvarchar(max)
DECLARE enacur CURSOR LOCAL FOR
SELECT FKRebuildScript, FKCheckScript FROM #FKScripts
OPEN enacur
FETCH NEXT FROM enacur INTO #enablesql, #checksql
WHILE ##FETCH_STATUS = 0 BEGIN
--execute your sproc on each row
EXEC sp_executesql #enablesql
EXEC sp_executesql #checksql
FETCH NEXT FROM enacur INTO #enablesql, #checkSQL
END
CLOSE enacur
DEALLOCATE enacur
/* Let's check that the constraints are now enabled again (for testing) */
SELECT DISTINCT
fkt.*
,CASE WHEN ((C.Status & 0x4000)) = 0 THEN 1 ELSE 0 END [Enabled3]
FROM #FKScripts fkt
INNER JOIN sys.sysobjects o2
ON o2.name = fkt.PKName
INNER JOIN sys.sysobjects o
ON o2.id = o.parent_obj
AND o.xtype='F'
INNER JOIN sys.sysconstraints c
ON o.id = c.constid

SQL Server database creation scripts in Visual Studio

As part of a ASP.NET MVC project I'm working on, I'll be working with SQL Server 2008 Express.
I'm not sure how I should go about having a version-controllable (I'm using Mercurial) way of recreating the database.
Ideally it should be run every time I perform a build in Visual Studio 2008.
EDIT 1: In response to couple of the answers, I'm using Visual Studio 2008 Professional Edition, which I have recieved via the Dreamspark program.
There are a couple ways of accomplishing this depending on some of your project specifics. We have .sql files that when executed recreate the database. This allows the scripts to go into your source control and be versioned just like everything else. It also allows for change scripts to be added once a product is in production.
We use this to drop all the objects in our database:
private static void DropDatabaseObjects()
{
var dropDatabaseObjects =
#"
/* Drop all non-system stored procs */
DECLARE #name VARCHAR(128)
DECLARE #constraint VARCHAR(254)
DECLARE #SQL VARCHAR(254)
SELECT #name = (SELECT TOP 1 [name] FROM sysobjects WHERE [type] = 'P' AND category = 0 ORDER BY [name])
WHILE #name is not null
BEGIN
SELECT #SQL = 'DROP PROCEDURE [dbo].[' + RTRIM(#name) +']'
EXEC (#SQL)
PRINT 'Dropped Procedure: ' + #name
SELECT #name = (SELECT TOP 1 [name] FROM sysobjects WHERE [type] = 'P' AND category = 0 AND [name] > #name ORDER BY [name])
END
/* Drop all views */
SELECT #name = (SELECT TOP 1 [name] FROM sysobjects WHERE [type] = 'V' AND category = 0 ORDER BY [name])
WHILE #name IS NOT NULL
BEGIN
SELECT #SQL = 'DROP VIEW [dbo].[' + RTRIM(#name) +']'
EXEC (#SQL)
PRINT 'Dropped View: ' + #name
SELECT #name = (SELECT TOP 1 [name] FROM sysobjects WHERE [type] = 'V' AND category = 0 AND [name] > #name ORDER BY [name])
END
/* Drop all functions */
SELECT #name = (SELECT TOP 1 [name] FROM sysobjects WHERE [type] IN (N'FN', N'IF', N'TF', N'FS', N'FT') AND category = 0 ORDER BY [name])
WHILE #name IS NOT NULL
BEGIN
SELECT #SQL = 'DROP FUNCTION [dbo].[' + RTRIM(#name) +']'
EXEC (#SQL)
PRINT 'Dropped Function: ' + #name
SELECT #name = (SELECT TOP 1 [name] FROM sysobjects WHERE [type] IN (N'FN', N'IF', N'TF', N'FS', N'FT') AND category = 0 AND [name] > #name ORDER BY [name])
END
/* Drop all Foreign Key constraints */
SELECT #name = (SELECT TOP 1 TABLE_NAME FROM INFORMATION_SCHEMA.TABLE_CONSTRAINTS WHERE constraint_catalog=DB_NAME() AND CONSTRAINT_TYPE = 'FOREIGN KEY' ORDER BY TABLE_NAME)
WHILE #name is not null
BEGIN
SELECT #constraint = (SELECT TOP 1 CONSTRAINT_NAME FROM INFORMATION_SCHEMA.TABLE_CONSTRAINTS WHERE constraint_catalog=DB_NAME() AND CONSTRAINT_TYPE = 'FOREIGN KEY' AND TABLE_NAME = #name ORDER BY CONSTRAINT_NAME)
WHILE #constraint IS NOT NULL
BEGIN
SELECT #SQL = 'ALTER TABLE [dbo].[' + RTRIM(#name) +'] DROP CONSTRAINT ' + RTRIM(#constraint)
EXEC (#SQL)
PRINT 'Dropped FK Constraint: ' + #constraint + ' on ' + #name
SELECT #constraint = (SELECT TOP 1 CONSTRAINT_NAME FROM INFORMATION_SCHEMA.TABLE_CONSTRAINTS WHERE constraint_catalog=DB_NAME() AND CONSTRAINT_TYPE = 'FOREIGN KEY' AND CONSTRAINT_NAME <> #constraint AND TABLE_NAME = #name ORDER BY CONSTRAINT_NAME)
END
SELECT #name = (SELECT TOP 1 TABLE_NAME FROM INFORMATION_SCHEMA.TABLE_CONSTRAINTS WHERE constraint_catalog=DB_NAME() AND CONSTRAINT_TYPE = 'FOREIGN KEY' ORDER BY TABLE_NAME)
END
/* Drop all Primary Key constraints */
SELECT #name = (SELECT TOP 1 TABLE_NAME FROM INFORMATION_SCHEMA.TABLE_CONSTRAINTS WHERE constraint_catalog=DB_NAME() AND CONSTRAINT_TYPE = 'PRIMARY KEY' ORDER BY TABLE_NAME)
WHILE #name IS NOT NULL
BEGIN
SELECT #constraint = (SELECT TOP 1 CONSTRAINT_NAME FROM INFORMATION_SCHEMA.TABLE_CONSTRAINTS WHERE constraint_catalog=DB_NAME() AND CONSTRAINT_TYPE = 'PRIMARY KEY' AND TABLE_NAME = #name ORDER BY CONSTRAINT_NAME)
WHILE #constraint is not null
BEGIN
SELECT #SQL = 'ALTER TABLE [dbo].[' + RTRIM(#name) +'] DROP CONSTRAINT ' + RTRIM(#constraint)
EXEC (#SQL)
PRINT 'Dropped PK Constraint: ' + #constraint + ' on ' + #name
SELECT #constraint = (SELECT TOP 1 CONSTRAINT_NAME FROM INFORMATION_SCHEMA.TABLE_CONSTRAINTS WHERE constraint_catalog=DB_NAME() AND CONSTRAINT_TYPE = 'PRIMARY KEY' AND CONSTRAINT_NAME <> #constraint AND TABLE_NAME = #name ORDER BY CONSTRAINT_NAME)
END
SELECT #name = (SELECT TOP 1 TABLE_NAME FROM INFORMATION_SCHEMA.TABLE_CONSTRAINTS WHERE constraint_catalog=DB_NAME() AND CONSTRAINT_TYPE = 'PRIMARY KEY' ORDER BY TABLE_NAME)
END
/* Drop all tables */
SELECT #name = (SELECT TOP 1 [name] FROM sysobjects WHERE [type] = 'U' AND category = 0 ORDER BY [name])
WHILE #name IS NOT NULL
BEGIN
SELECT #SQL = 'DROP TABLE [dbo].[' + RTRIM(#name) +']'
EXEC (#SQL)
PRINT 'Dropped Table: ' + #name
SELECT #name = (SELECT TOP 1 [name] FROM sysobjects WHERE [type] = 'U' AND category = 0 AND [name] > #name ORDER BY [name])
END";
using (var connection = new SqlConnection(GetConnectionStringFromHibernateConfiguration("hibernate.cfg.xml")))
using (var command = new SqlCommand(dropDatabaseObjects, connection))
{
connection.Open();
command.ExecuteNonQuery();
connection.Close();
}
}
We use this to recreate our database (assuming the dbScriptFolder contains .sql files that will create all the tables, views, stored procs, etc):
private static void RecreateDatabase()
{
var directoryInfo = new DirectoryInfo(ConfigurationManager.AppSettings["dbScriptFolder"]);
using (var connection = new SqlConnection(GetConnectionStringFromHibernateConfiguration("hibernate.cfg.xml")))
{
connection.Open();
foreach (var fileInfo in directoryInfo.GetFiles())
{
if (fileInfo.Extension == ".sql")
{
var script = ReadFromFile(fileInfo);
var server = new Server(new ServerConnection(connection));
server.ConnectionContext.ExecuteNonQuery(script);
}
}
connection.Close();
}
}
These methods get called in a base testfixture method for when we run our integration tests so we know we're working with our database in a known state.
If you're looking to do this as part of a build script, have a look at the Tarantino project here and here
Have a look at Visual Studio Team System 2008 Database Edition GDR (Or DataDude)
This allows you to store and work with database schemas and artefacts (tables, procedures, triggers... pretty much everything). It also allows comparing one schema against another, or against an instance of a database and will generated change/deployment scripts.
There is support for reference data too (although this isn't great at this stage in the products life).
There is also integration with MSBuild - I'm using this on a large project now, every time we do a build, a schema file is generated which we then use to actually generate the scripts to apply to a given database (Using VSDBCMD.EXE). We don't currently automatically push these changes out but doing so is not too difficult.
Are you using Visual Studio Team Suite or Visual Studio Developer Edition? If so, Visual Studio Database Edition is free, and a fantastic way to manage your database schema. Has about all the features you could want.
Randy

Resources