How to drop all tables in a SQL Server database? - sql-server

I'm trying to write a script that will completely empty a SQL Server database. This is what I have so far:
USE [dbname]
GO
EXEC sp_msforeachtable 'ALTER TABLE ? NOCHECK CONSTRAINT all'
EXEC sp_msforeachtable 'DELETE ?'
When I run it in the Management Studio, I get:
Command(s) completed successfully.
but when I refresh the table list, they are all still there. What am I doing wrong?

You can also delete all tables from database using only MSSMS UI tools (without using SQL script). Sometimes this way can be more comfortable (especially if it is performed occasionally)
I do this step by step as follows:
Select 'Tables' on the database tree (Object Explorer)
Press F7 to open Object Explorer Details view
In this view select tables which have to be deleted (in this case all of them)
Keep pressing Delete until all tables have been deleted (you repeat it as many times as amount of errors due to key constraints/dependencies)

It doesn't work for me either when there are multiple foreign key tables.
I found that code that works and does everything you try (delete all tables from your database):
DECLARE #Sql NVARCHAR(500) DECLARE #Cursor CURSOR
SET #Cursor = CURSOR FAST_FORWARD FOR
SELECT DISTINCT sql = 'ALTER TABLE [' + tc2.TABLE_SCHEMA + '].[' + tc2.TABLE_NAME + '] DROP [' + rc1.CONSTRAINT_NAME + '];'
FROM INFORMATION_SCHEMA.REFERENTIAL_CONSTRAINTS rc1
LEFT JOIN INFORMATION_SCHEMA.TABLE_CONSTRAINTS tc2 ON tc2.CONSTRAINT_NAME =rc1.CONSTRAINT_NAME
OPEN #Cursor FETCH NEXT FROM #Cursor INTO #Sql
WHILE (##FETCH_STATUS = 0)
BEGIN
Exec sp_executesql #Sql
FETCH NEXT FROM #Cursor INTO #Sql
END
CLOSE #Cursor DEALLOCATE #Cursor
GO
EXEC sp_MSforeachtable 'DROP TABLE ?'
GO
You can find the post here. It is the post by Groker.

In SSMS:
Right click the database
Go to "Tasks"
Click "Generate Scripts"
In the "Choose Objects" section, select "Script entire database and all database objects"
In the "Set Scripting Options" section, click the "Advanced" button
On "Script DROP and CREATE" switch "Script CREATE" to "Script DROP" and press OK
Then, either save to file, clipboard, or new query window.
Run script.
Now, this will drop everything, including the database. Make sure to remove the code for the items you don't want dropped. Alternatively, in the "Choose Objects" section, instead of selecting to script entire database just select the items you want to remove.

The accepted answer doesn't support Azure. It uses an undocumented stored procedure "sp_MSforeachtable". If you get an "azure could not find stored procedure 'sp_msforeachtable" error when running or simply want to avoid relying on undocumented features (which can be removed or have their functionality changed at any point) then try the below.
This version ignores the entity framework migration history table "__MigrationHistory" and the "database_firewall_rules" which is an Azure table you will not have permission to delete.
Lightly tested on Azure. Do check to make this this has no undesired effects on your environment.
DECLARE #sql NVARCHAR(2000)
WHILE(EXISTS(SELECT 1 from INFORMATION_SCHEMA.TABLE_CONSTRAINTS WHERE CONSTRAINT_TYPE='FOREIGN KEY'))
BEGIN
SELECT TOP 1 #sql=('ALTER TABLE ' + TABLE_SCHEMA + '.[' + TABLE_NAME + '] DROP CONSTRAINT [' + CONSTRAINT_NAME + ']')
FROM INFORMATION_SCHEMA.TABLE_CONSTRAINTS
WHERE CONSTRAINT_TYPE = 'FOREIGN KEY'
EXEC(#sql)
PRINT #sql
END
WHILE(EXISTS(SELECT * from INFORMATION_SCHEMA.TABLES WHERE TABLE_NAME != '__MigrationHistory' AND TABLE_NAME != 'database_firewall_rules'))
BEGIN
SELECT TOP 1 #sql=('DROP TABLE ' + TABLE_SCHEMA + '.[' + TABLE_NAME + ']')
FROM INFORMATION_SCHEMA.TABLES
WHERE TABLE_NAME != '__MigrationHistory' AND TABLE_NAME != 'database_firewall_rules'
EXEC(#sql)
PRINT #sql
END
Taken from:
https://edspencer.me.uk/2013/02/25/drop-all-tables-in-a-sql-server-database-azure-friendly/
http://www.sqlservercentral.com/blogs/sqlservertips/2011/10/11/remove-all-foreign-keys/

delete is used for deleting rows from a table. You should use drop table instead.
EXEC sp_msforeachtable 'drop table [?]'

/* 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 [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
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 [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
GO

You are almost right, use instead:
EXEC sp_msforeachtable 'ALTER TABLE ? NOCHECK CONSTRAINT all'
EXEC sp_msforeachtable 'DROP TABLE ?'
but second line you might need to execute more then once until you stop getting error:
Could not drop object 'dbo.table' because it is referenced by a FOREIGN KEY constraint.
Message:
Command(s) completed successfully.
means that all table were successfully deleted.

Short and sweet:
USE YOUR_DATABASE_NAME
-- Disable all referential integrity constraints
EXEC sp_MSforeachtable 'ALTER TABLE ? NOCHECK CONSTRAINT ALL'
GO
-- Drop all PKs and FKs
declare #sql nvarchar(max)
SELECT #sql = STUFF((SELECT '; ' + 'ALTER TABLE ' + Table_Name +' drop constraint ' + Constraint_Name from Information_Schema.CONSTRAINT_TABLE_USAGE ORDER BY Constraint_Name FOR XML PATH('')),1,1,'')
EXECUTE (#sql)
GO
-- Drop all tables
EXEC sp_MSforeachtable 'DROP TABLE ?'
GO

Spot on!!
You can use below query to remove all the tables from database
EXEC sp_MSforeachtable #command1 = "DROP TABLE ?"
Happy coding !

Seems the command should be without the square blanket
EXEC sp_msforeachtable 'drop table ?'

The fasted way is:
New Database Diagrams
Add all table
Ctrl + A to select all
Right Click "Remove from Database"
Ctrl + S to save
Enjoy

For me, the easiest way:
--First delete all constraints
DECLARE #sql NVARCHAR(MAX);
SET #sql = N'';
SELECT #sql = #sql + N'
ALTER TABLE ' + QUOTENAME(s.name) + N'.'
+ QUOTENAME(t.name) + N' DROP CONSTRAINT '
+ QUOTENAME(c.name) + ';'
FROM sys.objects AS c
INNER JOIN sys.tables AS t
ON c.parent_object_id = t.[object_id]
INNER JOIN sys.schemas AS s
ON t.[schema_id] = s.[schema_id]
WHERE c.[type] IN ('D','C','F','PK','UQ')
ORDER BY c.[type];
EXEC sys.sp_executesql #sql;
-- Then drop all tables
exec sp_MSforeachtable 'DROP TABLE ?'

Azure SQL + tables (with constraints) in a different schema than dbo + ipv6_database_firewall_rules condition.
This is a little extension for https://stackoverflow.com/a/43128914/4510954 answer.
DECLARE #sql NVARCHAR(2000)
WHILE(EXISTS(SELECT 1 from INFORMATION_SCHEMA.TABLE_CONSTRAINTS WHERE CONSTRAINT_TYPE='FOREIGN KEY'))
BEGIN
SELECT TOP 1 #sql=('ALTER TABLE ' + CONSTRAINT_SCHEMA + '.[' + TABLE_NAME + '] DROP CONSTRAINT [' + CONSTRAINT_NAME + ']')
FROM INFORMATION_SCHEMA.TABLE_CONSTRAINTS
WHERE CONSTRAINT_TYPE = 'FOREIGN KEY'
EXEC(#sql)
PRINT #sql
END
WHILE(EXISTS(SELECT * from INFORMATION_SCHEMA.TABLES WHERE TABLE_NAME != '__MigrationHistory' AND TABLE_NAME != 'database_firewall_rules' AND TABLE_NAME != 'ipv6_database_firewall_rules'))
BEGIN
SELECT TOP 1 #sql=('DROP TABLE ' + CONSTRAINT_SCHEMA + '.[' + TABLE_NAME + ']')
FROM INFORMATION_SCHEMA.TABLE_CONSTRAINTS
WHERE TABLE_NAME != '__MigrationHistory' AND TABLE_NAME != 'database_firewall_rules'
EXEC(#sql)
PRINT #sql
END

How about dropping the entire database and then creating it again? This works for me.
DROP DATABASE mydb;
CREATE DATABASE mydb;

For Temporal Tables it is a bit more complicated due to the fact there may be some foreign keys and also exception:
Drop table operation failed on table XXX because it is not a supported operation on system-versioned temporal tables
What you can use is:
-- Disable constraints (foreign keys)
EXEC sp_MSForEachTable 'ALTER TABLE ? NOCHECK CONSTRAINT ALL'
GO
-- Disable system versioning (temporial tables)
EXEC sp_MSForEachTable '
IF OBJECTPROPERTY(object_id(''?''), ''TableTemporalType'') = 2
ALTER TABLE ? SET (SYSTEM_VERSIONING = OFF)
'
GO
-- Removing tables
EXEC sp_MSForEachTable 'DROP TABLE ?'
GO

I know this is an old post now but I have tried all the answers on here on a multitude of databases and I have found they all work sometimes but not all of the time for various (I can only assume) quirks of SQL Server.
Eventually I came up with this. I have tested this everywhere (generally speaking) I can and it works (without any hidden store procedures).
For note mostly on SQL Server 2014. (but most of the other versions I tried it also seems to worked fine).
I have tried while loops and nulls etc etc, cursors and various other forms but they always seem to fail on some databases but not others for no obvious reason.
Getting a count and using that to iterate always seems to work on everything Ive tested.
USE [****YOUR_DATABASE****]
GO
SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO
-- Drop all referential integrity constraints --
-- Drop all Primary Key constraints. --
DECLARE #sql NVARCHAR(296)
DECLARE #table_name VARCHAR(128)
DECLARE #constraint_name VARCHAR(128)
SET #constraint_name = ''
DECLARE #row_number INT
SELECT #row_number = Count(*) FROM INFORMATION_SCHEMA.REFERENTIAL_CONSTRAINTS rc1
LEFT JOIN INFORMATION_SCHEMA.TABLE_CONSTRAINTS tc2 ON tc2.CONSTRAINT_NAME = rc1.CONSTRAINT_NAME
WHILE #row_number > 0
BEGIN
BEGIN
SELECT TOP 1 #table_name = tc2.TABLE_NAME, #constraint_name = rc1.CONSTRAINT_NAME FROM INFORMATION_SCHEMA.REFERENTIAL_CONSTRAINTS rc1
LEFT JOIN INFORMATION_SCHEMA.TABLE_CONSTRAINTS tc2 ON tc2.CONSTRAINT_NAME = rc1.CONSTRAINT_NAME
AND rc1.CONSTRAINT_NAME > #constraint_name
ORDER BY rc1.CONSTRAINT_NAME
SELECT #sql = 'ALTER TABLE [dbo].[' + RTRIM(#table_name) +'] DROP CONSTRAINT [' + RTRIM(#constraint_name)+']'
EXEC (#sql)
PRINT 'Dropped Constraint: ' + #constraint_name + ' on ' + #table_name
SET #row_number = #row_number - 1
END
END
GO
-- Drop all tables --
DECLARE #sql NVARCHAR(156)
DECLARE #name VARCHAR(128)
SET #name = ''
DECLARE #row_number INT
SELECT #row_number = Count(*) FROM sysobjects WHERE [type] = 'U' AND category = 0
WHILE #row_number > 0
BEGIN
SELECT #name = (SELECT TOP 1 [name] FROM sysobjects WHERE [type] = 'U' AND category = 0 AND [name] > #name ORDER BY [name])
SELECT #sql = 'DROP TABLE [dbo].[' + RTRIM(#name) +']'
EXEC (#sql)
PRINT 'Dropped Table: ' + #name
SET #row_number = #row_number - 1
END
GO

sp_msforeachtable is not available in Azure SQL
For Azure SQL:
This query will drop Foreign Key constraints
DECLARE #Name VARCHAR(200)
DECLARE #Constraint VARCHAR(300)
DECLARE #SQL VARCHAR(300)
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
GO
This will drop all the tables from the database
DECLARE #Name VARCHAR(200)
DECLARE #SQL VARCHAR(300)
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) +']' /*here you can change schema if it is different from dbo*/
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

Related

SQL Server Query to show table name and specific column name and current value in all user table

All of our user tables have a primary key and a rowid_time column. We would like to develop a SQL query which lists:
table name
the value of the primary key
the value of the rowid_time column
(only these three columns and NOT ALL columns of the table)
for all rows and tables in the database.
Is that doable? Ideally this is delivered via a database view.
With dynamic SQL and using a SQL cursor, we can solve the requirement as follows
DECLARE #TableName sysname
DECLARE #SQL nvarchar(max)
DECLARE #PKColumnList nvarchar(max)
DECLARE mycursor CURSOR FAST_FORWARD
FOR
SELECT name FROM sys.tables order by Name
OPEN mycursor
FETCH NEXT FROM mycursor INTO #TableName
WHILE ##FETCH_STATUS = 0
BEGIN
----------------
SELECT #PKColumnList = string_agg(COLUMN_NAME, ',')
FROM INFORMATION_SCHEMA.CONSTRAINT_COLUMN_USAGE a
WHERE
EXISTS(
SELECT *
FROM INFORMATION_SCHEMA.TABLE_CONSTRAINTS b
WHERE CONSTRAINT_TYPE = 'PRIMARY KEY'
AND a.CONSTRAINT_NAME = b.CONSTRAINT_NAME) AND
TABLE_NAME = #tablename
SET #PKColumnList = concat(#PKColumnList+',','rowid_time')
SELECT #SQL = '
;with t1 as (
select ''' + #TableName + ''' as TableName
), t2 as (
SELECT
''' + #TableName + ''' as TableName,
COUNT(*) OVER (Partition By 1) as RowsCount, '
+ #PKColumnList +
' FROM [' + #TableName + ']
)
select
t1.TableName,
t2.RowsCount, '
+ #PKColumnList + '
from t1
full join t2
on t1.TableName = t2.TableName'
EXEC SP_EXECUTESQL #SQL
-----------------
FETCH NEXT FROM mycursor INTO #TableName
END
CLOSE mycursor
DEALLOCATE mycursor
If the PK column for all tables is ID column (no composite key and all PK fields are named as ID for all tables), then SQL sp_MSForEachTable procedure can be used as follows
EXEC sp_MSForEachTable 'SELECT ''?'' as TableName, ID, rowid_time FROM ?'

Wipe out all data in a scheme, leave structure intact

We're going to be going through a period of testing on a product soon. This product is a web application with a SQL Server 2008R2 backend.
Our database has several schemas within it (Customer, DataEntry, and a few others).
I have found ways to wipe all data in a database without breaking referential integrity or the data structures, which is close to what we're looking to do. The problem I'm finding is that we actually need a bunch of the data from some of the tables. Essentially, we only want to wipe the Customers schema.
We have a script written which will load in the test data for customers, but is there a way to change the techniques in my linked article to target only a specific schema? Is there a better way to clear all data in a schema?
A common scenario for me as well. I usually write what I call a reset script, deleting all data form the target tables in the order necessary to prevent referential errors, and then reseed the primary keys.
DELETE FROM < table 1 >
DELETE FROM < table 2 >
... etc ...
DBCC CHECKIDENT (< table 1 >, RESEED, 0)
DBCC CHECKIDENT (< table 2 >, RESEED, 0)
... etc ...
EDIT
To more fully answer the original question. to leave data in specific tables you would need to modify the block of code that does the deleting / truncating, and also modify the code that reseeds the idents in a similar way.
EXEC sp_MSForEachTable '
IF object_id(''?'') != < table name > AND object_id(''?'') != < table name > AND ... etc ...
BEGIN
IF OBJECTPROPERTY(object_id(''?''), ''TableHasForeignRef'') = 1
DELETE FROM ?
ELSE
TRUNCATE TABLE ?
END
'
GO
Just set the #schemaID to the name of the schema you wish to blow away and it should do the rest. If you end up with a FK dependency loop it will break and tell you what to do...
Declare #schemaID Nvarchar(256)
Set #schemaID = 'Schema' -- Set this to the name of the schema you wish to blow away
If Object_ID('tempdb..#tables') Is Not Null Drop Table #tables
Create Table #tables (tID Int, SchemaName Nvarchar(256), TableName Nvarchar(256))
Insert #tables
Select Row_Number() Over (Order By s.name, so.name), s.name, so.name
From sysobjects so
Join sys.schemas s
On so.uid = s.schema_id
Where so.xtype = 'u'
And s.name = #schemaID
Declare #SQL Nvarchar(Max),
#schema Nvarchar(256),
#table Nvarchar(256),
#iter Int = 1,
#loopCatch Int = 0
While Exists (Select 1
From #tables)
Begin
Select #schema = SchemaName,
#table = TableName
From #tables
Where tID = #iter
If Exists (Select 1
From sysobjects o
Join sys.schemas s1
On o.uid = s1.schema_id
Join sysforeignkeys fk
On o.id = fk.rkeyid
Join sysobjects o2
On fk.fkeyid = o2.id
Join sys.schemas s2
On o2.uid = s2.schema_id
Join #tables t
On o2.name = t.TableName Collate Database_Default
And s2.name = t.SchemaName Collate Database_Default
Where o.name = #table
And s1.name = #schema)
Begin
Update t
Set tID = (Select Max(tID) From #tables) + 1
From #tables t
Where tableName = #table
And schemaName = #schema
Set #iter = #iter + 1
End
Else
Begin
Set #Sql = 'Truncate Table [' + #schema + '].[' + #table + ']'
Begin Try
Exec sp_executeSQL #SQL;
Delete t
From #tables t
Where tableName = #table
And schemaName = #schema
Set #iter = #iter + 1
End Try
Begin Catch
Print #SQL
Update t
Set tID = (Select Max(tID) From #tables) + 1
From #tables t
Where tableName = #table
And schemaName = #schema
Set #iter = #iter + 1
Set #loopCatch = #loopCatch + 1;
If #loopCatch > 5
Begin
Select 'WARNING: Endless FK redundancy loop. Drop the constraints and these tables, truncate and reapply constraints manually'
Union All
Select '[' + SchemaName + '].[' + TableName + ']'
From #tables;
Break;
End
End Catch
End
End
This is parameterized on database and schema. If no schema is supplied, it will clear all data in the specified database.
Handles tables with foreign key references appropriately by disabling constraints. If the procedure fails, which it shouldn't normally do, ensure that you run it successfully after fixing the cause of the problem, which should ensure constraint checking goes back to normal.
This will not handle foreign key references correctly if you have foreign keys between schemas, however, it could be fairly easily amended to handle this.
create procedure [removeData] (#database_name sysname, #schema_name sysname = null)
as
set nocount on
create table #tables (
TableName varchar(900) not null primary key,
HasFKRef bit not null
);
declare #sql nvarchar(4000),
#table_name varchar(900);
if (db_id(#database_name) is null)
raiserror ('You must at least specify the database name', 16, 1);
set #sql = 'select ''['' + TABLE_CATALOG + ''].['' + TABLE_SCHEMA + ''].['' + TABLE_NAME + '']'' as TableName, (case when exists(select * from [' + #database_name + '].INFORMATION_SCHEMA.REFERENTIAL_CONSTRAINTS rc inner join [' + #database_name + '].INFORMATION_SCHEMA.TABLE_CONSTRAINTS tc on rc.UNIQUE_CONSTRAINT_CATALOG = tc.CONSTRAINT_CATALOG and rc.UNIQUE_CONSTRAINT_SCHEMA = tc.CONSTRAINT_SCHEMA and rc.UNIQUE_CONSTRAINT_NAME = tc.CONSTRAINT_NAME where tc.TABLE_NAME = t.TABLE_NAME) then 1 else 0 end) as HasFKRef
from [' + #database_name + '].INFORMATION_SCHEMA.TABLES t
where TABLE_TYPE = ''BASE TABLE'' and TABLE_SCHEMA = isnull(#schema_name, TABLE_SCHEMA)';
insert into #tables
exec sp_executesql #sql, N'#schema_name sysname', #schema_name;
declare #curse cursor
set #curse = cursor fast_forward for
select sql from (
select 'alter table ' + TableName + ' nocheck constraint all' as sql, 1 as sort
from #tables
union all
select 'truncate table ' + TableName, 2 as sort
from #tables
where HasFKRef = 0
union all
select 'delete from ' + TableName, 3 as sort
from #tables
where HasFKRef = 1
union all
select 'alter table ' + TableName + ' with check check constraint all', 4 as sort
from #tables
) t
order by sort, sql
open #curse
fetch next from #curse into #sql
while (##fetch_status = 0)
begin
exec (#sql)
fetch next from #curse into #sql
end
close #curse
GO

How can I drop a table if there is a foreign key constraint in SQL Server?

I have the following:
DROP TABLE [dbo].[ExtraUserInformation];
DROP TABLE [dbo].[UserProfile];
DROP TABLE [dbo].[webpages_Membership];
DROP TABLE [dbo].[webpages_OAuthMembership];
DROP TABLE [dbo].[webpages_Roles];
DROP TABLE [dbo].[webpages_UsersInRoles];
CREATE TABLE [dbo].[ExtraUserInformation] (
[Id] INT IDENTITY (1, 1) NOT NULL,
[UserId] INT NOT NULL,
[FullName] NVARCHAR (MAX) NULL,
[Link] NVARCHAR (MAX) NULL,
[Verified] BIT NULL,
CONSTRAINT [PK_dbo.ExtraUserInformation] PRIMARY KEY CLUSTERED ([Id] ASC)
);
CREATE TABLE [dbo].[webpages_UsersInRoles] (
[UserId] INT NOT NULL,
[RoleId] INT NOT NULL,
PRIMARY KEY CLUSTERED ([UserId] ASC, [RoleId] ASC),
CONSTRAINT [fk_UserId] FOREIGN KEY ([UserId]) REFERENCES [dbo].[UserProfile] ([UserId]),
CONSTRAINT [fk_RoleId] FOREIGN KEY ([RoleId]) REFERENCES [dbo].[webpages_Roles] ([RoleId])
);
However this is failing with a message saying:
Msg 3726, Level 16, State 1, Line 6
Could not drop object 'dbo.UserProfile' because it is referenced by a FOREIGN KEY constraint.
Msg 3726, Level 16, State 1, Line 9
Could not drop object 'dbo.webpages_Roles' because it is referenced by a FOREIGN KEY constraint.
Msg 2714, Level 16, State 6, Line 27
There is already an object named 'UserProfile' in the database.
Checking identity information: current identity value 'NULL', current column value 'NULL'.
DBCC execution completed. If DBCC printed error messages, contact your system administrator.
How can I drop a table in these circumstances?
You must drop the constraint before you can drop the table. Otherwise its rule violation that could break the databases Referential Integrity.
How to get foreign key relationships see this old question.
SQL DROP TABLE foreign key constraint
1-firstly, drop the foreign key constraint after that drop the tables.
2-you can drop all foreign key via executing the following query:
DECLARE #SQL varchar(4000)=''
SELECT #SQL =
#SQL + 'ALTER TABLE ' + s.name+'.'+t.name + ' DROP CONSTRAINT [' + RTRIM(f.name) +'];' + CHAR(13)
FROM sys.Tables t
INNER JOIN sys.foreign_keys f ON f.parent_object_id = t.object_id
INNER JOIN sys.schemas s ON s.schema_id = f.schema_id
--EXEC (#SQL)
PRINT #SQL
if you execute the printed results #SQL, the foreign keys will be dropped.
The Best Answer to dropping the table containing foreign constraints is :
Step 1 : Drop the Primary key of the table.
Step 2 : Now it will prompt whether to delete all the foreign references or not.
Step 3 : Delete the table.
To drop a table if there is a foreign key constraint in MySQL Server?
Run the sql query:
SET FOREIGN_KEY_CHECKS = 0;
DROP TABLE table_name
Hope it helps!
--Find and drop the constraints
DECLARE #dynamicSQL VARCHAR(MAX)
DECLARE MY_CURSOR CURSOR
LOCAL STATIC READ_ONLY FORWARD_ONLY
FOR
SELECT dynamicSQL = 'ALTER TABLE [' + OBJECT_SCHEMA_NAME(parent_object_id) + '].[' + OBJECT_NAME(parent_object_id) + '] DROP CONSTRAINT [' + name + ']'
FROM sys.foreign_keys
WHERE object_name(referenced_object_id) in ('table1', 'table2', 'table3')
OPEN MY_CURSOR
FETCH NEXT FROM MY_CURSOR INTO #dynamicSQL
WHILE ##FETCH_STATUS = 0
BEGIN
PRINT #dynamicSQL
EXEC (#dynamicSQL)
FETCH NEXT FROM MY_CURSOR INTO #dynamicSQL
END
CLOSE MY_CURSOR
DEALLOCATE MY_CURSOR
-- Drop tables
DROP 'table1'
DROP 'table2'
DROP 'table3'
You have to drop the constraint before drop your table.
You can use those queries to find all FKs in your table and find the FKs in the tables in which your table is used.
Declare #SchemaName VarChar(200) = 'Your Schema name'
Declare #TableName VarChar(200) = 'Your Table Name'
-- Find FK in This table.
SELECT
' IF EXISTS (SELECT * FROM sys.foreign_keys WHERE object_id =
OBJECT_ID(N''' +
'[' + OBJECT_SCHEMA_NAME(FK.parent_object_id) + '].[' + FK.name + ']'
+ ''') AND parent_object_id = OBJECT_ID(N''' +
'[' + OBJECT_SCHEMA_NAME(FK.parent_object_id) + '].[' +
OBJECT_NAME(FK.parent_object_id) + ']' + ''')) ' +
'ALTER TABLE ' + OBJECT_SCHEMA_NAME(FK.parent_object_id) +
'.[' + OBJECT_NAME(FK.parent_object_id) +
'] DROP CONSTRAINT ' + FK.name
, S.name , O.name, OBJECT_NAME(FK.parent_object_id)
FROM sys.foreign_keys AS FK
INNER JOIN Sys.objects As O
ON (O.object_id = FK.parent_object_id )
INNER JOIN SYS.schemas AS S
ON (O.schema_id = S.schema_id)
WHERE
O.name = #TableName
And S.name = #SchemaName
-- Find the FKs in the tables in which this table is used
SELECT
' IF EXISTS (SELECT * FROM sys.foreign_keys WHERE object_id =
OBJECT_ID(N''' +
'[' + OBJECT_SCHEMA_NAME(FK.parent_object_id) + '].[' + FK.name + ']'
+ ''') AND parent_object_id = OBJECT_ID(N''' +
'[' + OBJECT_SCHEMA_NAME(FK.parent_object_id) + '].[' +
OBJECT_NAME(FK.parent_object_id) + ']' + ''')) ' +
' ALTER TABLE ' + OBJECT_SCHEMA_NAME(FK.parent_object_id) +
'.[' + OBJECT_NAME(FK.parent_object_id) +
'] DROP CONSTRAINT ' + FK.name
, S.name , O.name, OBJECT_NAME(FK.parent_object_id)
FROM sys.foreign_keys AS FK
INNER JOIN Sys.objects As O
ON (O.object_id = FK.referenced_object_id )
INNER JOIN SYS.schemas AS S
ON (O.schema_id = S.schema_id)
WHERE
O.name = #TableName
And S.name = #SchemaName
BhupeshC and murat , this is what I was looking for. However #SQL varchar(4000) wasn't big enough. So, small change
DECLARE #cmd varchar(4000)
DECLARE MY_CURSOR CURSOR
LOCAL STATIC READ_ONLY FORWARD_ONLY
FOR
select 'ALTER TABLE ['+s.name+'].['+t.name+'] DROP CONSTRAINT [' + RTRIM(f.name) +'];' FROM sys.Tables t INNER JOIN sys.foreign_keys f ON f.parent_object_id = t.object_id INNER JOIN sys.schemas s ON s.schema_id = f.schema_id
OPEN MY_CURSOR
FETCH NEXT FROM MY_CURSOR INTO #cmd
WHILE ##FETCH_STATUS = 0
BEGIN
-- EXEC (#cmd)
PRINT #cmd
FETCH NEXT FROM MY_CURSOR INTO #cmd
END
CLOSE MY_CURSOR
DEALLOCATE MY_CURSOR
GO
Re removing constraints and dropping the tables, this script can get all constraints for a selected list of tables and then drop the constraints and then delete the tables.
DECLARE #id INT
DECLARE #strSQL NVARCHAR(max)
DECLARE #deleteCurser CURSOR
DECLARE #deleteTableCurser CURSOR
declare #SelectedTables table ([name] sysname, [object_id] int)
Insert into #SelectedTables ([name], [object_id])
SELECT t.name, t.object_id
FROM sys.Tables t
where t.name in
-- Change Name of tables here
('table1','table2','table100')
SET #deleteTableCurser = CURSOR FOR
SELECT strSQL =
'ALTER TABLE ' + s.name+'.'+t.name + ' DROP CONSTRAINT [' + RTRIM(f.name) +'];'
FROM #SelectedTables t
INNER JOIN sys.foreign_keys f ON f.parent_object_id = t.object_id
INNER JOIN sys.schemas s ON s.schema_id = f.schema_id
OPEN #deleteTableCurser
FETCH Next
FROM #deleteTableCurser INTO #strSQL
WHILE ##FETCH_STATUS = 0
BEGIN
print(#strSQL)
EXEC (#strSQL)
FETCH NEXT
FROM #deleteTableCurser INTO #strSQL
END
CLOSE #deleteTableCurser
DEALLOCATE #deleteTableCurser
SET #deleteCurser = CURSOR FOR
SELECT strSQL = 'DROP TABLE ['+ t.name+ '];'
FROM #SelectedTables t
OPEN #deleteCurser
FETCH Next
FROM #deleteCurser INTO #strSQL
WHILE ##FETCH_STATUS = 0
BEGIN
print(#strSQL)
EXEC (#strSQL)
FETCH NEXT
FROM #deleteCurser INTO #strSQL
END
CLOSE #deleteCurser
DEALLOCATE #deleteCurser
Type this .... SET foreign_key_checks = 0;
delete your table then type SET foreign_key_checks = 1;
MySQL – Temporarily disable Foreign Key Checks or Constraints

Temporarily disable all foreign key constraints

I am running an SSIS package which will replace data for a few tables from FlatFiles to existing tables in a database.
My package will truncate the tables and then insert the new data. When I run my SSIS package, I get an exception because of the foreign keys.
Can I disable the constraints, run my import, then re-enable them?
To disable foreign key constraints:
DECLARE #sql nvarchar(max) = N'';
;WITH x AS
(
SELECT DISTINCT obj =
QUOTENAME(OBJECT_SCHEMA_NAME(parent_object_id)) + '.'
+ QUOTENAME(OBJECT_NAME(parent_object_id))
FROM sys.foreign_keys
)
SELECT #sql += N'ALTER TABLE ' + obj + N' NOCHECK CONSTRAINT ALL;
' FROM x;
EXEC sys.sp_executesql #sql;
To re-enable:
DECLARE #sql nvarchar(max) = N'';
;WITH x AS
(
SELECT DISTINCT obj =
QUOTENAME(OBJECT_SCHEMA_NAME(parent_object_id)) + '.'
+ QUOTENAME(OBJECT_NAME(parent_object_id))
FROM sys.foreign_keys
)
SELECT #sql += N'ALTER TABLE ' + obj + N' WITH CHECK CHECK CONSTRAINT ALL;
' FROM x;
EXEC sys.sp_executesql #sql;
However, you will not be able to truncate the tables, you will have to delete from them in the right order. If you need to truncate them, you need to drop the constraints entirely, and re-create them. This is simple to do if your foreign key constraints are all simple, single-column constraints, but definitely more complex if there are multiple columns involved.
Here is something you can try. In order to make this a part of your SSIS package you'll need a place to store the FK definitions while the SSIS package runs (you won't be able to do this all in one script). So in some utility database, create a table:
CREATE TABLE dbo.PostCommand(cmd nvarchar(max));
Then in your database, you can have a stored procedure that does this:
DELETE other_database.dbo.PostCommand;
DECLARE #sql nvarchar(max) = N'';
SELECT #sql += N'ALTER TABLE '
+ QUOTENAME(OBJECT_SCHEMA_NAME(fk.parent_object_id))
+ '.' + QUOTENAME(OBJECT_NAME(fk.parent_object_id))
+ ' ADD CONSTRAINT ' + fk.name + ' FOREIGN KEY ('
+ STUFF((SELECT ',' + c.name
FROM sys.columns AS c
INNER JOIN sys.foreign_key_columns AS fkc
ON fkc.parent_column_id = c.column_id
AND fkc.parent_object_id = c.[object_id]
WHERE fkc.constraint_object_id = fk.[object_id]
ORDER BY fkc.constraint_column_id
FOR XML PATH(''),
TYPE).value(N'./text()[1]', 'nvarchar(max)'), 1, 1, N'')
+ ') REFERENCES ' +
QUOTENAME(OBJECT_SCHEMA_NAME(fk.referenced_object_id))
+ '.' + QUOTENAME(OBJECT_NAME(fk.referenced_object_id))
+ '(' +
STUFF((SELECT ',' + c.name
FROM sys.columns AS c
INNER JOIN sys.foreign_key_columns AS fkc
ON fkc.referenced_column_id = c.column_id
AND fkc.referenced_object_id = c.[object_id]
WHERE fkc.constraint_object_id = fk.[object_id]
ORDER BY fkc.constraint_column_id
FOR XML PATH(''),
TYPE).value(N'./text()[1]', N'nvarchar(max)'), 1, 1, N'') + ');
' FROM sys.foreign_keys AS fk
WHERE OBJECTPROPERTY(parent_object_id, 'IsMsShipped') = 0;
INSERT other_database.dbo.PostCommand(cmd) SELECT #sql;
IF ##ROWCOUNT = 1
BEGIN
SET #sql = N'';
SELECT #sql += N'ALTER TABLE ' + QUOTENAME(OBJECT_SCHEMA_NAME(fk.parent_object_id))
+ '.' + QUOTENAME(OBJECT_NAME(fk.parent_object_id))
+ ' DROP CONSTRAINT ' + fk.name + ';
' FROM sys.foreign_keys AS fk;
EXEC sys.sp_executesql #sql;
END
Now when your SSIS package is finished, it should call a different stored procedure, which does:
DECLARE #sql nvarchar(max);
SELECT #sql = cmd FROM other_database.dbo.PostCommand;
EXEC sys.sp_executesql #sql;
If you're doing all of this just for the sake of being able to truncate instead of delete, I suggest just taking the hit and running a delete. Maybe use bulk-logged recovery model to minimize the impact of the log. In general I don't see how this solution will be all that much faster than just using a delete in the right order.
In 2014 I published a more elaborate post about this here:
Drop and Re-Create All Foreign Key Constraints in SQL Server
Use the built-in sp_msforeachtable stored procedure.
To disable all constraints:
EXEC sp_msforeachtable "ALTER TABLE ? NOCHECK CONSTRAINT ALL";
To enable all constraints:
EXEC sp_msforeachtable "ALTER TABLE ? WITH CHECK CHECK CONSTRAINT ALL";
To drop all the tables:
EXEC sp_msforeachtable "DROP TABLE ?";
A good reference is given at : http://msdn.microsoft.com/en-us/magazine/cc163442.aspx
under the section "Disabling All Foreign Keys"
Inspired from it, an approach can be made by creating a temporary table and inserting the constraints in that table, and then dropping the constraints and then reapplying them from that temporary table. Enough said here is what i am talking about
SET NOCOUNT ON
DECLARE #temptable TABLE(
Id INT PRIMARY KEY IDENTITY(1, 1),
FKConstraintName VARCHAR(255),
FKConstraintTableSchema VARCHAR(255),
FKConstraintTableName VARCHAR(255),
FKConstraintColumnName VARCHAR(255),
PKConstraintName VARCHAR(255),
PKConstraintTableSchema VARCHAR(255),
PKConstraintTableName VARCHAR(255),
PKConstraintColumnName VARCHAR(255)
)
INSERT INTO #temptable(FKConstraintName, FKConstraintTableSchema, FKConstraintTableName, FKConstraintColumnName)
SELECT
KeyColumnUsage.CONSTRAINT_NAME,
KeyColumnUsage.TABLE_SCHEMA,
KeyColumnUsage.TABLE_NAME,
KeyColumnUsage.COLUMN_NAME
FROM
INFORMATION_SCHEMA.KEY_COLUMN_USAGE KeyColumnUsage
INNER JOIN INFORMATION_SCHEMA.TABLE_CONSTRAINTS TableConstraints
ON KeyColumnUsage.CONSTRAINT_NAME = TableConstraints.CONSTRAINT_NAME
WHERE
TableConstraints.CONSTRAINT_TYPE = 'FOREIGN KEY'
UPDATE #temptable SET
PKConstraintName = UNIQUE_CONSTRAINT_NAME
FROM
#temptable tt
INNER JOIN INFORMATION_SCHEMA.REFERENTIAL_CONSTRAINTS ReferentialConstraint
ON tt.FKConstraintName = ReferentialConstraint.CONSTRAINT_NAME
UPDATE #temptable SET
PKConstraintTableSchema = TABLE_SCHEMA,
PKConstraintTableName = TABLE_NAME
FROM #temptable tt
INNER JOIN INFORMATION_SCHEMA.TABLE_CONSTRAINTS TableConstraints
ON tt.PKConstraintName = TableConstraints.CONSTRAINT_NAME
UPDATE #temptable SET
PKConstraintColumnName = COLUMN_NAME
FROM #temptable tt
INNER JOIN INFORMATION_SCHEMA.KEY_COLUMN_USAGE KeyColumnUsage
ON tt.PKConstraintName = KeyColumnUsage.CONSTRAINT_NAME
--Now to drop constraint:
SELECT
'
ALTER TABLE [' + FKConstraintTableSchema + '].[' + FKConstraintTableName + ']
DROP CONSTRAINT ' + FKConstraintName + '
GO'
FROM
#temptable
--Finally to add constraint:
SELECT
'
ALTER TABLE [' + FKConstraintTableSchema + '].[' + FKConstraintTableName + ']
ADD CONSTRAINT ' + FKConstraintName + ' FOREIGN KEY(' + FKConstraintColumnName + ') REFERENCES [' + PKConstraintTableSchema + '].[' + PKConstraintTableName + '](' + PKConstraintColumnName + ')
GO'
FROM
#temptable
GO
There is an easy way to this.
-- Disable all the constraint in database
EXEC sp_msforeachtable 'ALTER TABLE ? NOCHECK CONSTRAINT all'
-- Enable all the constraint in database
EXEC sp_msforeachtable 'ALTER TABLE ? WITH CHECK CHECK CONSTRAINT all'
Reference SQL SERVER – Disable All the Foreign Key Constraint in Database – Enable All the Foreign Key Constraint in Database
Disable all table constraints
ALTER TABLE TableName NOCHECK CONSTRAINT ConstraintName
-- Enable all table constraints
ALTER TABLE TableName CHECK CONSTRAINT ConstraintName
In case you use a different database schemas than ".dbo" or your db is containing Pk´s, which are composed by several fields, please don´t use the the solution of Carter Medlin, otherwise you will damage your db!!!
When you are working with different schemas try this (don´t forget to make a backup of your database before!):
DECLARE #sql AS NVARCHAR(max)=''
select #sql = #sql +
'ALTER INDEX ALL ON ' + SCHEMA_NAME( t.schema_id) +'.'+ '['+ t.[name] + '] DISABLE;'+CHAR(13)
from
sys.tables t
where type='u'
select #sql = #sql +
'ALTER INDEX ' + i.[name] + ' ON ' + SCHEMA_NAME( t.schema_id) +'.'+'[' + t.[name] + '] REBUILD;'+CHAR(13)
from
sys.key_constraints i
join
sys.tables t on i.parent_object_id=t.object_id
where i.type='PK'
exec dbo.sp_executesql #sql;
go
After doing some Fk-free actions, you can switch back with
DECLARE #sql AS NVARCHAR(max)=''
select #sql = #sql +
'ALTER INDEX ALL ON ' + SCHEMA_NAME( t.schema_id) +'.'+'[' + t.[name] + '] REBUILD;'+CHAR(13)
from
sys.tables t
where type='u'
print #sql
exec dbo.sp_executesql #sql;
exec sp_msforeachtable "ALTER TABLE ? WITH NOCHECK CHECK CONSTRAINT ALL";
not need to run queries to sidable FKs on sql. If you have a FK from table A to B, you should:
delete data from table A
delete data from table B
insert data on B
insert data on A
You can also tell the destination not to check constraints
Truncating the table wont be possible even if you disable the foreign keys.so you can use
delete command to remove all the records from the table,but be aware if you are using delete
command for a table which consists of millions of records then your package will be slow
and your transaction log size will increase and it may fill up your valuable disk space.
If you drop the constraints it may happen that you will fill up your table with unclean data
and when you try to recreate the constraints it may not allow you to as it will give errors.
so make sure that if you drop the constraints,you are loading data which are correctly related to each other and satisfy the constraint relations which you are going to recreate.
so please carefully think the pros and cons of each method and use it according to your requirements
Disable all indexes (including the pk, which will disable all fks), then reenable the pks.
DECLARE #sql AS NVARCHAR(max)=''
select #sql = #sql +
'ALTER INDEX ALL ON [' + t.[name] + '] DISABLE;'+CHAR(13)
from
sys.tables t
where type='u'
select #sql = #sql +
'ALTER INDEX ' + i.[name] + ' ON [' + t.[name] + '] REBUILD;'+CHAR(13)
from
sys.key_constraints i
join
sys.tables t on i.parent_object_id=t.object_id
where
i.type='PK'
exec dbo.sp_executesql #sql;
go
[Do your data load]
Then bring everything back to life...
DECLARE #sql AS NVARCHAR(max)=''
select #sql = #sql +
'ALTER INDEX ALL ON [' + t.[name] + '] REBUILD;'+CHAR(13)
from
sys.tables t
where type='u'
exec dbo.sp_executesql #sql;
go

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