Related
One of our SQL Databases is a sync of somebody else's Database. There are about 100 tables in their database, and about 120 in ours.
In ours, we have a few additional tables that help us do mapping and track other data. As a part of our additional tables, we create Foreign Keys onto some of the DBO Tables that are Sync'd from our provider.
Therefore, a Customers table that is sync'd from our Provider now has Foreign Key constraints on a mySchema.Receipts table, which has a CustomerID field.
The Provider's Sync broke, and they said that they cannot Drop the Customers table in order to Sync the data, because it now says there is a Foriegn key against Customers.
Isn't there a way I can tell them in SQL that SQL can like... ignore Foriegn Key constraints when Sync'ing or something?
If the sync job is deleting data from the target database, you can disable constraints, and then enable them again after the sync. If your sync job is truncating tables or drop and rebuilding tables, them the foreign key constraints need to be dropped, then rebuilt again after the sync.
Using the "delete from target" approach:
If target tables are part of the "dbo" schema, your process could look like:
(1) Disable all foreign keys constrains in target database.
Example:
exec sp_MSforeachtable 'IF ''?'' like ''%[dbo]%'' ALTER TABLE ? NOCHECK CONSTRAINT ALL;'
(2) Delete all data from the target tables
(3) Copy all data from the source to the target tables, including identity column data if needed.
(4) Restore all foreign keys constrains in target database.
Example:
exec sp_MSforeachtable 'IF ''?'' like ''%[dbo]%'' ALTER TABLE ? CHECK CONSTRAINT ALL;'
** To help further automate this, take advantage of the INFORMATION_SCHEMA.TABLES view in SQL Server.
SELECT 'dbo.' + TABLE_NAME as TableName, 'SELECT * FROM dbo.['+ TABLE_NAME +'];' AS Script FROM INFORMATION_SCHEMA.TABLES WHERE TABLE_SCHEMA = 'dbo' and TABLE_NAME NOT IN (comma delimited list of tables to exclude)
If needed, the below script will query all of the foreign key constraints:
IF OBJECT_ID('tempdb..#TEMPCONS') IS NOT NULL DROP TABLE #TEMPCONS;
SELECT KCU1.TABLE_SCHEMA, KCU1.TABLE_NAME, KCU1.CONSTRAINT_NAME, KCU1.COLUMN_NAME, KCU1.ORDINAL_POSITION, RC.UPDATE_RULE, RC.DELETE_RULE,
KCU2.TABLE_NAME AS REF_TABLE_NAME, KCU2.CONSTRAINT_NAME AS REF_CONSTRAINT_NAME, KCU2.COLUMN_NAME AS REF_COLUMN_NAME, KCU2.ORDINAL_POSITION AS REF_ORDINAL_POSITION,
KCU2.TABLE_SCHEMA AS REF_TABLE_SCHEMA INTO #TEMPCONS
FROM INFORMATION_SCHEMA.REFERENTIAL_CONSTRAINTS RC INNER JOIN
INFORMATION_SCHEMA.KEY_COLUMN_USAGE KCU1 ON KCU1.CONSTRAINT_CATALOG = RC.CONSTRAINT_CATALOG AND
KCU1.CONSTRAINT_SCHEMA = RC.CONSTRAINT_SCHEMA AND KCU1.CONSTRAINT_NAME = RC.CONSTRAINT_NAME INNER JOIN
INFORMATION_SCHEMA.KEY_COLUMN_USAGE KCU2 ON KCU2.CONSTRAINT_CATALOG = RC.UNIQUE_CONSTRAINT_CATALOG AND
KCU2.CONSTRAINT_SCHEMA = RC.UNIQUE_CONSTRAINT_SCHEMA AND KCU2.CONSTRAINT_NAME = RC.UNIQUE_CONSTRAINT_NAME AND
KCU2.ORDINAL_POSITION = KCU1.ORDINAL_POSITION
ORDER BY TABLE_NAME, CONSTRAINT_NAME, ORDINAL_POSITION;
ALTER TABLE #TEMPCONS ADD COLUMN_LIST VARCHAR(MAX), REF_COLUMN_LIST VARCHAR(MAX);
-- Rows to column concatenation
DECLARE #COLUMN_NAME varchar(MAX), #Columns VARCHAR(MAX);
UPDATE #TEMPCONS SET #Columns = COLUMN_LIST = COALESCE(CASE COALESCE(#COLUMN_NAME, '')
WHEN CONSTRAINT_NAME THEN #Columns + ', ' + '['+ COLUMN_NAME +']' ELSE '['+ COLUMN_NAME +']' END, ''), #COLUMN_NAME = CONSTRAINT_NAME;
UPDATE #TEMPCONS SET #Columns = REF_COLUMN_LIST = COALESCE( CASE COALESCE(#COLUMN_NAME, '')
WHEN CONSTRAINT_NAME THEN #Columns + ', ' + '['+REF_COLUMN_NAME +']' ELSE '['+REF_COLUMN_NAME +']' END, ''), #COLUMN_NAME = CONSTRAINT_NAME;
SELECT TABLE_SCHEMA, TABLE_NAME, CONSTRAINT_NAME, UPDATE_RULE, DELETE_RULE, MAX(COLUMN_LIST) AS COLUMN_LIST,
REF_TABLE_SCHEMA, REF_TABLE_NAME, REF_CONSTRAINT_NAME, MAX(REF_COLUMN_LIST) AS REF_COLUMN_LIST
FROM #TEMPCONS
GROUP BY REF_TABLE_SCHEMA, TABLE_SCHEMA, TABLE_NAME, CONSTRAINT_NAME, UPDATE_RULE, DELETE_RULE, REF_TABLE_NAME, REF_CONSTRAINT_NAME;
I have a requirement where I need to create a foreign key for more than 200 tables. Ex, there is emp table which has ID has primary key, now the 200 tables have emp_id, which I need to reference to emp.id.
I know I can write 200 alter statements to create the foreign key. Is there an easier way to create with one simple script?
Please advise. Thanks for your help.
Here is a trick to do it
DECLARE #sql NVARCHAR(max)=''
SELECT #sql += '
ALTER TABLE ' + Object_name(object_id)
+ '
ADD CONSTRAINT FK_'
+ Object_name(object_id)
+ '_EMP_emp_id FOREIGN KEY (emp_id) REFERENCES EMP(id);'
FROM sys.COLUMNS
WHERE NAME = 'emp_id'
--Print #sql
EXEC Sp_executesql
#sql
Note :
Print #SQL variable and check the generated SQL is good
Above code consider's all the 200 table has the same name 'emp_id' to which foreign key is created
This may fail when the 'emp_id' column has bad data (ie) a 'emp_id' which is not present in EMP table
You could probably generate the alter table statements dynamically using information_schema.columns. Something like this should get you started:
SELECT 'ALTER TABLE '+ TABLE_NAME +
' ADD CONSTRAINT FK_'+ TABLE_NAME +'_Emp FOREIGN KEY ('+ COLUMN_NAME +')'+
' REFERENCES emp (Id)'+
' ON DELETE CASCADE'+
' ON UPDATE CASCADE;'+
' GO '
FROM INFORMATION_SCHEMA.COLUMNS
WHERE COLUMN_NAME = 'emp_id'
This question already has answers here:
Finding a Primary Key Constraint on the fly in SQL Server 2005
(4 answers)
Closed 5 years ago.
I need to drop the primary key of a table Student in a SQL Server database.
I have edited in the table and the script I got is
ALTER TABLE dbo.Student
DROP CONSTRAINT PK__Student__9CC368536561EF8B
But when I run this script in SQL Server query browser to drop the primary key
It shows the message
Msg 3728, Level 16, State 1, Line 1
'PK__Student__9CC368536561EF8B' is not a constraint.
Msg 3727, Level 16, State 0, Line 1
To my concern I think PK__Student__9CC368536561EF8B this will be generated randomly
please help me to drop the primary key constraint using script.
Thanks in advance
You can look up the constraint name in the sys.key_constraints table:
SELECT name
FROM sys.key_constraints
WHERE [type] = 'PK'
AND [parent_object_id] = Object_id('dbo.Student');
If you don't care about the name, but simply want to drop it, you can use a combination of this and dynamic sql:
DECLARE #table NVARCHAR(512), #sql NVARCHAR(MAX);
SELECT #table = N'dbo.Student';
SELECT #sql = 'ALTER TABLE ' + #table
+ ' DROP CONSTRAINT ' + name + ';'
FROM sys.key_constraints
WHERE [type] = 'PK'
AND [parent_object_id] = OBJECT_ID(#table);
EXEC sp_executeSQL #sql;
This code is from Aaron Bertrand (source).
simply click
'Database'>tables>your table name>keys>copy the constraints like 'PK__TableName__30242045'
and run the below query is :
Query:alter Table 'TableName' drop constraint PK__TableName__30242045
The answer I got is that variables and subqueries
will not work and we have to user dynamic SQL script. The following works:
DECLARE #SQL VARCHAR(4000)
SET #SQL = 'ALTER TABLE dbo.Student DROP CONSTRAINT |ConstraintName| '
SET #SQL = REPLACE(#SQL, '|ConstraintName|', ( SELECT name
FROM sysobjects
WHERE xtype = 'PK'
AND parent_obj = OBJECT_ID('Student')))
EXEC (#SQL)
I want to remove foreign key from another table so i can insert values of my choice.
I am new in databases so please tell me correct sql query to drop or remove foreign key value.
Try following
ALTER TABLE <TABLE_NAME> DROP CONSTRAINT <FOREIGN_KEY_NAME>
Refer : http://www.w3schools.com/sql/sql_foreignkey.asp
Its wrong to do that in refer to referential integrity, because once its broken its not easy to turn it on again without having to go through the records and delete the ones which breaks the constraints.
Anyway the Syntax is as follows:
ALTER TABLE Tablename DROP CONSTRAINT ContName;
See MSDN:
Delete Primary Keys
Delete Foreign Key Relationships
ALTER TABLE [TableName] DROP CONSTRAINT [CONSTRAINT_NAME]
But, be careful man, once you do that, you may never get a chance back, and you should read some basic database book see why we need foreign key
To remove all the constraints from the DB:
SELECT 'ALTER TABLE ' + Table_Name +' DROP CONSTRAINT ' + Constraint_Name
FROM Information_Schema.CONSTRAINT_TABLE_USAGE
You should consider (temporarily) disabling the constraint before you completely delete it.
If you look at the table creation TSQL you will see something like:
ALTER TABLE [dbo].[dbAccounting] CHECK CONSTRAINT [FK_some_FK_constraint]
You can run
ALTER TABLE [dbo].[dbAccounting] NOCHECK CONSTRAINT [FK_some_FK_constraint]
... then insert/update a bunch of values that violate the constraint, and then turn it back on by running the original CHECK statement.
(I have had to do this to cleanup poorly designed systems I've inherited in the past.)
Drop all the foreign keys of a table:
USE [Database_Name]
DECLARE #FOREIGN_KEY_NAME VARCHAR(100)
DECLARE FOREIGN_KEY_CURSOR CURSOR FOR
SELECT name FOREIGN_KEY_NAME FROM sys.foreign_keys WHERE parent_object_id = (SELECT object_id FROM sys.objects WHERE name = 'Table_Name' AND TYPE = 'U')
OPEN FOREIGN_KEY_CURSOR
----------------------------------------------------------
FETCH NEXT FROM FOREIGN_KEY_CURSOR INTO #FOREIGN_KEY_NAME
WHILE ##FETCH_STATUS = 0
BEGIN
DECLARE #DROP_COMMAND NVARCHAR(150) = 'ALTER TABLE Table_Name DROP CONSTRAINT' + ' ' + #FOREIGN_KEY_NAME
EXECUTE Sp_executesql #DROP_COMMAND
FETCH NEXT FROM FOREIGN_KEY_CURSOR INTO #FOREIGN_KEY_NAME
END
-----------------------------------------------------------------------------------------------------------------
CLOSE FOREIGN_KEY_CURSOR
DEALLOCATE FOREIGN_KEY_CURSOR
Depending on the DB you are using there's a syntax or another.
If you're using Oracle you have to put what the other users told you:
ALTER TABLE table_name DROP CONSTRAINT fk_name;
But if you use MySQL then this will give you a syntax error, instead you can type:
ALTER TABLE table_name DROP INDEX fk_name;
firstly use
show create table table_name;
to see the descriptive structure of your table.
There you may see constraints respective to foreign keys you used in that table.
First delete the respective constraint with
alter table table_name drop constraint constraint_name;
and then delete the respective foreign keys or column you wanted...GoodLuck!!
ALTER TABLE table
DROP FOREIGN KEY fk_key
EDIT: didn't notice you were using sql-server, my bad
ALTER TABLE table
DROP CONSTRAINT fk_key
Use those queries to find all FKs:
Declare #SchemaName VarChar(200) = 'Schema Name'
Declare #TableName VarChar(200) = '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
Alternatively, you can also delete a Foreign Key Constraint from the SQL Server Management Studio itself. You can try it if the commands do not work.
Expand your database view.
Right Click on Table which has foreign key constraint. Choose Design. A tab with the information about table columns will open.
Right click on the column which has the foreign key reference. Or you can right click on any column. Choose Relationships.
A list of relationships will appear (if you have one) in a pop up window.
From there you can delete the foreign key constraint.
I hope that helps
If you find yourself in a situation where the FK name of a table has been auto-generated and you aren't able to view what it exactly is (in the case of not having rights to a database for instance) you could try something like this:
DECLARE #table NVARCHAR(512), #sql NVARCHAR(MAX);
SELECT #table = N'dbo.Table';
SELECT #sql = 'ALTER TABLE ' + #table
+ ' DROP CONSTRAINT ' + NAME + ';'
FROM sys.foreign_keys
WHERE [type] = 'F'
AND [parent_object_id] = OBJECT_ID(#table);
EXEC sp_executeSQL #sql;
Build up a stored proc which drops the constraint of the specified table without specifying the actual FK name. It drops the constraint where the object [type] is equal to F (Foreign Key constraint).
Note: if there are multiple FK's in the table it will drop them all. So this solution works best if the table you are targeting has just one FK.
If you don't know foreign key constraint name then try this to find it.
sp_help 'TableName'
additionally for different schema
sp_help 'schemaName.TableName'
then
ALTER TABLE <TABLE_NAME> DROP CONSTRAINT <FOREIGN_KEY_NAME>
To be on the safer side, just name all your constraints and take note of them in the comment section.
ALTER TABLE[table_name]
DROP CONSTRAINT Constraint_name
alter table <referenced_table_name> drop primary key;
Foreign key constraint will be removed.
I have a test environment for a database that I want to reload with new data at the start of a testing cycle. I am not interested in rebuilding the entire database- just simply "re-setting" the data.
What is the best way to remove all the data from all the tables using TSQL? Are there system stored procedures, views, etc. that can be used? I do not want to manually create and maintain truncate table statements for each table- I would prefer it to be dynamic.
When dealing with deleting data from tables which have foreign key relationships - which is basically the case with any properly designed database - we can disable all the constraints, delete all the data and then re-enable constraints
-- disable all constraints
EXEC sp_MSForEachTable "ALTER TABLE ? NOCHECK CONSTRAINT all"
-- delete data in all tables
EXEC sp_MSForEachTable "DELETE FROM ?"
-- enable all constraints
exec sp_MSForEachTable "ALTER TABLE ? WITH CHECK CHECK CONSTRAINT all"
More on disabling constraints and triggers here
if some of the tables have identity columns we may want to reseed them
EXEC sp_MSForEachTable "DBCC CHECKIDENT ( '?', RESEED, 0)"
Note that the behaviour of RESEED differs between brand new table, and one which had had some data inserted previously from BOL:
DBCC CHECKIDENT ('table_name', RESEED, newReseedValue)
The current identity value is set to
the newReseedValue. If no rows have
been inserted to the table since it
was created, the first row inserted
after executing DBCC CHECKIDENT will
use newReseedValue as the identity.
Otherwise, the next row inserted will
use newReseedValue + 1. If the value
of newReseedValue is less than the
maximum value in the identity column,
error message 2627 will be generated
on subsequent references to the table.
Thanks to Robert for pointing out the fact that disabling constraints does not allow to use truncate, the constraints would have to be dropped, and then recreated
For SQL 2005,
EXEC sp_MSForEachTable 'TRUNCATE TABLE ?'
Couple more links for 2000 and 2005/2008..
Here's the king daddy of database wiping scripts. It will clear all tables and reseed them correctly:
SET QUOTED_IDENTIFIER ON;
EXEC sp_MSforeachtable 'SET QUOTED_IDENTIFIER ON; ALTER TABLE ? NOCHECK CONSTRAINT ALL'
EXEC sp_MSforeachtable 'SET QUOTED_IDENTIFIER ON; ALTER TABLE ? DISABLE TRIGGER ALL'
EXEC sp_MSforeachtable 'SET QUOTED_IDENTIFIER ON; DELETE FROM ?'
EXEC sp_MSforeachtable 'SET QUOTED_IDENTIFIER ON; ALTER TABLE ? CHECK CONSTRAINT ALL'
EXEC sp_MSforeachtable 'SET QUOTED_IDENTIFIER ON; ALTER TABLE ? ENABLE TRIGGER ALL'
EXEC sp_MSforeachtable 'SET QUOTED_IDENTIFIER ON';
IF NOT EXISTS (
SELECT
*
FROM
SYS.IDENTITY_COLUMNS
JOIN SYS.TABLES ON SYS.IDENTITY_COLUMNS.Object_ID = SYS.TABLES.Object_ID
WHERE
SYS.TABLES.Object_ID = OBJECT_ID('?') AND SYS.IDENTITY_COLUMNS.Last_Value IS NULL
)
AND OBJECTPROPERTY( OBJECT_ID('?'), 'TableHasIdentity' ) = 1
DBCC CHECKIDENT ('?', RESEED, 0) WITH NO_INFOMSGS;
Enjoy, but be careful!
The simplest way of doing this is to
open up SQL Management Studio
navigate to your database
Right-click and select Tasks->Generate Scripts (pic 1)
On the "choose Objects" screen, select the "select specific objects" option and check "tables" (pic 2)
on the next screen, select "advanced" and then change the "Script DROP and CREATE" option to "Script DROP and CREATE" (pic 3)
Choose to save script to a new editor window or a file and run as necessary.
this will give you a script that drops and recreates all your tables without the need to worry about debugging or whether you've included everything. While this performs more than just a truncate, the results are the same. Just keep in mind that your auto-incrementing primary keys will start at 0, as opposed to truncated tables which will remember the last value assigned. You can also execute this from code if you don't have access to Management studio on your PreProd or Production environments.
1.
2.
3.
Truncating all of the tables will only work if you don't have any foreign key relationships between your tables, as SQL Server will not allow you to truncate a table with a foreign key.
An alternative to this is to determine the tables with foreign keys and delete from these first, you can then truncate the tables without foreign keys afterwards.
See http://www.sqlteam.com/forums/topic.asp?TOPIC_ID=65341 and http://www.sqlteam.com/forums/topic.asp?TOPIC_ID=72957 for further details.
Don't do this! Really, not a good idea.
If you know which tables you want to truncate, create a stored procedure which truncates them. You can fix the order to avoid foreign key problems.
If you really want to truncate them all (so you can BCP load them for example) you would be just as quick to drop the database and create a new one from scratch, which would have the additional benefit that you know exactly where you are.
An alternative option I like to use with MSSQL Server Deveploper or Enterprise is to create a snapshot of the database immediately after creating the empty schema. At that point you can just keep restoring the database back to the snapshot.
If you want to keep data in a particular table (i.e. a static lookup table) while deleting/truncating data in other tables within the same db, then you need a loop with the exceptions in it. This is what I was looking for when I stumbled onto this question.
sp_MSForEachTable seems buggy to me (i.e. inconsistent behavior with IF statements) which is probably why its undocumented by MS.
declare #LastObjectID int = 0
declare #TableName nvarchar(100) = ''
set #LastObjectID = (select top 1 [object_id] from sys.tables where [object_id] > #LastObjectID order by [object_id])
while(#LastObjectID is not null)
begin
set #TableName = (select top 1 [name] from sys.tables where [object_id] = #LastObjectID)
if(#TableName not in ('Profiles', 'ClientDetails', 'Addresses', 'AgentDetails', 'ChainCodes', 'VendorDetails'))
begin
exec('truncate table [' + #TableName + ']')
end
set #LastObjectID = (select top 1 [object_id] from sys.tables where [object_id] > #LastObjectID order by [object_id])
end
The hardest part of truncating all tables is removing and re-ading the foreign key constraints.
The following query creates the drop & create statements for each constraint relating to each table name in #myTempTable. If you would like to generate these for all the tables, you may simple use information schema to gather these table names instead.
DECLARE #myTempTable TABLE (tableName varchar(200))
INSERT INTO #myTempTable(tableName) VALUES
('TABLE_ONE'),
('TABLE_TWO'),
('TABLE_THREE')
-- DROP FK Contraints
SELECT 'alter table '+quotename(schema_name(ob.schema_id))+
'.'+quotename(object_name(ob.object_id))+ ' drop constraint ' + quotename(fk.name)
FROM sys.objects ob INNER JOIN sys.foreign_keys fk ON fk.parent_object_id = ob.object_id
WHERE fk.referenced_object_id IN
(
SELECT so.object_id
FROM sys.objects so JOIN sys.schemas sc
ON so.schema_id = sc.schema_id
WHERE so.name IN (SELECT * FROM #myTempTable) AND sc.name=N'dbo' AND type in (N'U'))
-- CREATE FK Contraints
SELECT 'ALTER TABLE [PIMSUser].[dbo].[' +cast(c.name as varchar(255)) + '] WITH NOCHECK ADD CONSTRAINT ['+ cast(f.name as varchar(255)) +'] FOREIGN KEY (['+ cast(fc.name as varchar(255)) +'])
REFERENCES [PIMSUser].[dbo].['+ cast(p.name as varchar(255)) +'] (['+cast(rc.name as varchar(255))+'])'
FROM sysobjects f
INNER JOIN sys.sysobjects c ON f.parent_obj = c.id
INNER JOIN sys.sysreferences r ON f.id = r.constid
INNER JOIN sys.sysobjects p ON r.rkeyid = p.id
INNER JOIN sys.syscolumns rc ON r.rkeyid = rc.id and r.rkey1 = rc.colid
INNER JOIN sys.syscolumns fc ON r.fkeyid = fc.id and r.fkey1 = fc.colid
WHERE
f.type = 'F'
AND
cast(p.name as varchar(255)) IN (SELECT * FROM #myTempTable)
I then just copy out the statements to run - but with a bit of dev effort you could use a cursor to run them dynamically.
It is much easier (and possibly even faster) to script out your database, then just drop and create it from the script.
Make an empty "template" database, take a full backup. When you need to refresh, just restore using WITH REPLACE. Fast, simple, bulletproof. And if a couple tables here or there need some base data(e.g. config information, or just basic information that makes your app run) it handles that too.
This is one way to do it... there are likely 10 others that are better/more efficient, but it sounds like this is done very infrequently, so here goes...
get a list of the tables from sysobjects, then loop over those with a cursor, calling sp_execsql('truncate table ' + #table_name) for each iteration.
Run the commented out section once, populate the _TruncateList table with the tables you want truncated, then run the rest of the script. The _ScriptLog table will need to be cleaned up over time if you do this a lot.
You can modify this if you want to do all tables, just put in SELECT name INTO #TruncateList FROM sys.tables. However, you usually don't want to do them all.
Also, this will affect all foreign keys in the database, and you can modify that as well if it's too blunt-force for your application. It's not for my purposes.
/*
CREATE TABLE _ScriptLog
(
ID Int NOT NULL Identity(1,1)
, DateAdded DateTime2 NOT NULL DEFAULT GetDate()
, Script NVarChar(4000) NOT NULL
)
CREATE UNIQUE CLUSTERED INDEX IX_ScriptLog_DateAdded_ID_U_C ON _ScriptLog
(
DateAdded
, ID
)
CREATE TABLE _TruncateList
(
TableName SysName PRIMARY KEY
)
*/
IF OBJECT_ID('TempDB..#DropFK') IS NOT NULL BEGIN
DROP TABLE #DropFK
END
IF OBJECT_ID('TempDB..#TruncateList') IS NOT NULL BEGIN
DROP TABLE #TruncateList
END
IF OBJECT_ID('TempDB..#CreateFK') IS NOT NULL BEGIN
DROP TABLE #CreateFK
END
SELECT Scripts = 'ALTER TABLE ' + '[' + OBJECT_NAME(f.parent_object_id)+ ']'+
' DROP CONSTRAINT ' + '[' + f.name + ']'
INTO #DropFK
FROM .sys.foreign_keys AS f
INNER JOIN .sys.foreign_key_columns AS fc
ON f.OBJECT_ID = fc.constraint_object_id
SELECT TableName
INTO #TruncateList
FROM _TruncateList
SELECT Scripts = 'ALTER TABLE ' + const.parent_obj + '
ADD CONSTRAINT ' + const.const_name + ' FOREIGN KEY (
' + const.parent_col_csv + '
) REFERENCES ' + const.ref_obj + '(' + const.ref_col_csv + ')
'
INTO #CreateFK
FROM (
SELECT QUOTENAME(fk.NAME) AS [const_name]
,QUOTENAME(schParent.NAME) + '.' + QUOTENAME(OBJECT_name(fkc.parent_object_id)) AS [parent_obj]
,STUFF((
SELECT ',' + QUOTENAME(COL_NAME(fcP.parent_object_id, fcp.parent_column_id))
FROM sys.foreign_key_columns AS fcP
WHERE fcp.constraint_object_id = fk.object_id
FOR XML path('')
), 1, 1, '') AS [parent_col_csv]
,QUOTENAME(schRef.NAME) + '.' + QUOTENAME(OBJECT_NAME(fkc.referenced_object_id)) AS [ref_obj]
,STUFF((
SELECT ',' + QUOTENAME(COL_NAME(fcR.referenced_object_id, fcR.referenced_column_id))
FROM sys.foreign_key_columns AS fcR
WHERE fcR.constraint_object_id = fk.object_id
FOR XML path('')
), 1, 1, '') AS [ref_col_csv]
FROM sys.foreign_key_columns AS fkc
INNER JOIN sys.foreign_keys AS fk ON fk.object_id = fkc.constraint_object_id
INNER JOIN sys.objects AS oParent ON oParent.object_id = fkc.parent_object_id
INNER JOIN sys.schemas AS schParent ON schParent.schema_id = oParent.schema_id
INNER JOIN sys.objects AS oRef ON oRef.object_id = fkc.referenced_object_id
INNER JOIN sys.schemas AS schRef ON schRef.schema_id = oRef.schema_id
GROUP BY fkc.parent_object_id
,fkc.referenced_object_id
,fk.NAME
,fk.object_id
,schParent.NAME
,schRef.NAME
) AS const
ORDER BY const.const_name
INSERT INTO _ScriptLog (Script)
SELECT Scripts
FROM #CreateFK
DECLARE #Cmd NVarChar(4000)
, #TableName SysName
WHILE 0 < (SELECT Count(1) FROM #DropFK) BEGIN
SELECT TOP 1 #Cmd = Scripts
FROM #DropFK
EXEC (#Cmd)
DELETE #DropFK WHERE Scripts = #Cmd
END
WHILE 0 < (SELECT Count(1) FROM #TruncateList) BEGIN
SELECT TOP 1 #Cmd = N'TRUNCATE TABLE ' + TableName
, #TableName = TableName
FROM #TruncateList
EXEC (#Cmd)
DELETE #TruncateList WHERE TableName = #TableName
END
WHILE 0 < (SELECT Count(1) FROM #CreateFK) BEGIN
SELECT TOP 1 #Cmd = Scripts
FROM #CreateFK
EXEC (#Cmd)
DELETE #CreateFK WHERE Scripts = #Cmd
END
It is a little late but it might help someone.
I created a procedure sometimes back which does the following using T-SQL:
Store all constraints in a Temporary table
Drop All Constraints
Truncate all tables with exception of some tables, which does not need truncation
Recreate all Constraints.
I have listed it on my blog here
I do not see why clearing data would be better than a script to drop and re-create each table.
That or keep a back up of your empty DB and restore it over old one
Before truncating the tables you have to remove all foreign keys. Use this script to generate final scripts to drop and recreate all foreign keys in database. Please set the #action variable to 'CREATE' or 'DROP'.
select 'delete from ' +TABLE_NAME from INFORMATION_SCHEMA.TABLES where TABLE_TYPE='BASE TABLE'
where result come.
Copy and paste on query window and run the command