Is it possible to search for records in Microsoft SQL Server manager?
I mean something like in VS pressing Ctrl-F and searching by word?
There is no way in searching for objects in SQL Server management studio. There are views and tables that can be used to search for objects like:
SELECT * FROM sys.tables WHERE name LIKE '%...%'
To search for tables.
If you mean, searching for data within a table, I need to learn T-SQL.
There are non-free 3rd party tools (ex. Redgate's SQL Search), but I use the proc below. You have to create the proc in every [master] database so it's available server-wide, but you can pass in a search term and an optional database name (otherwise it searches through object definitions in all databases):
USE [master]
GO
/****** Object: StoredProcedure [dbo].[sp_FindTextOnServer] Script Date: 10/6/2017 3:39:19 PM ******/
SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO
/*-----------------------------------------------------------
This procedure will search all or a specified database objects
for the supplied text and return a table with the values
Examples:
EXEC sp_FindTextOnServer 'Billing', 'fcsCore'
EXEC sp_FindTextOnServer 'vJurisdiction'
-----------------------------------------------------------*/
ALTER PROCEDURE [dbo].[sp_FindTextOnServer]
#text VARCHAR(40),
#searchDB VARCHAR(100) = NULL
AS
DECLARE #DisplayText VARCHAR(100),
#sSql VARCHAR(1000),
#line VARCHAR(300),
#char CHAR,
#lineNo INTEGER,
#counter INTEGER,
#AddedRecord BIT,
#dbObjectType VARCHAR(100),
#dbObject VARCHAR(100),
#ObjectBody VARCHAR(7000),
#dbName VARCHAR(100)
SET #DisplayText = #Text
SET #text = '%' + #text + '%'
SET #AddedRecord = 0
CREATE TABLE #SearchResults
(
DBName VARCHAR(100) NOT NULL,
ObjectType VARCHAR(100) NOT NULL,
ObjectName VARCHAR(100) NOT NULL,
Line INT NOT NULL,
Reference VARCHAR(7000) NOT NULL
)
CREATE TABLE #tempSysComments
(
DBName VARCHAR(100),
DBObjectType VARCHAR(100),
DBObject VARCHAR(100),
TextString text
)
--Populate a table with the search results from all databases on the server that include the searched text
SET #sSql = 'USE [?]
SELECT
''?'' AS DBName,
LOWER(REPLACE(o.type_desc, ''_'', '' '')) + '' ('' + RTRIM(type) + '')'' AS DBObjectType,
OBJECT_NAME(sm.object_id) AS DBObject,
CAST(sm.definition AS VARCHAR(7000)) AS TextString
FROM sys.sql_modules AS sm
JOIN sys.objects AS o
ON sm.object_id = o.object_id
WHERE CAST(sm.definition AS VARCHAR(7000)) LIKE ''' + #text + '''
ORDER BY o.type_desc, OBJECT_NAME(sm.object_id)'
IF (#searchDB IS NULL)
BEGIN
INSERT INTO #tempSysComments
EXEC sp_MSFOREachDB #sSql
END
ELSE
BEGIN
SET #sSql = REPLACE(#sSql, '?', #searchDB)
INSERT INTO #tempSysComments
EXEC (#sSql)
END
DECLARE codeCursor CURSOR
FOR
SELECT DBName, DBObjectType, DBObject, TextString
FROM #tempSysComments
WHERE DBName IS NOT NULL
OPEN codeCursor
FETCH NEXT FROM codeCursor INTO #dbName, #dbObjectType, #dbObject, #ObjectBody
IF ##FETCH_STATUS <> 0
BEGIN
PRINT 'Text ''' + #DisplayText + ''' was not found in objects on server ' + ##SERVERNAME
-- Close and release code cursor.
CLOSE codeCursor
DEALLOCATE codeCursor
RETURN
END
-- Search each object within code cursor.
WHILE ##FETCH_STATUS = 0
BEGIN
SET #lineNo = 0
SET #counter = 1
-- Process each line.
WHILE (#counter <> Len(#ObjectBody))
BEGIN
SET #char = SUBSTRING(#ObjectBody, #counter,1)
-- Check for line breaks.
IF (#char = CHAR(13))
BEGIN
SET #lineNo = #lineNo + 1
-- Check if we found the specified text.
IF (PATINDEX(#text, #line) <> 0)
BEGIN
SET #AddedRecord = 1
INSERT #SearchResults
SELECT #dbName, #dbObjectType, #dbObject, #lineNo, LEFT(RTRIM(LTRIM(#line)), 7000)
END
SET #line = ''
END
SET #line = #line + #char
SET #counter = #counter + 1
END
IF (#AddedRecord = 0)
INSERT #SearchResults
SELECT #dbName, #dbObjectType, #dbObject, 0, SUBSTRING(#ObjectBody, 1, 7000)
SET #AddedRecord = 0
FETCH NEXT FROM codeCursor INTO #dbName, #dbObjectType, #dbObject, #ObjectBody
END
-- Close and release cursor.
CLOSE codeCursor
DEALLOCATE codeCursor
-- Return the info.
SELECT DISTINCT DBName, ObjectType, ObjectName, Line, RTRIM(LTRIM(REPLACE(REPLACE(Reference, CHAR(9), ' '), CHAR(13)+CHAR(10), ' '))) AS Reference
FROM #SearchResults
ORDER BY DBName, ObjectType, ObjectName, Line
-- Cleanup.
DROP TABLE #SearchResults
DROP TABLE #tempSysComments
RETURN
Hi I need to create a view or stored procedure that combines data and returns a result set from 3 different databases on the same server using a column that holds a schema (db) name.
For Example on the first DB I have this table:
CREATE TABLE [dbo].[CloudUsers](
ID int IDENTITY(1,1) NOT NULL,
Username nvarchar(50) NULL,
MainDB nvarchar(100) NULL
) ON [PRIMARY]
Each CloudUser has a separate DB so next now I need to fetch the data from the User database using the MainDB name. The data I need is always 1 row cause I'm using aggregate functions / query.
So in the User MainDB let's say I have this table.
CREATE TABLE [dbo].[CLIENT](
ID int NOT NULL,
Name nvarchar(50) NULL,
ProjectDBName [nvarchar](100) NULL
CreationDate datetime NULL
) ON [PRIMARY]
And I query like:
select min(CreationDate) from MainDB.Client
The same Idea for the Client I need to fetch even more data from a 3rd database that points to the Client ProjectDBName. Again it's aggregate data:
select Count(id) as TotalTransactions from ProjectDBName.Journal
My final result should have records from all databases. It's readonly data that I need for statistics.
Final result set example:
CloudUsers.Username, MainDB->CreationDate, ProjectDBName->TotalTransaction
How can I achieve that ?
This is not easy - and without a schema and sample data, I can't give you a precise answer.
You need to iterate through each client, and use dynamic SQL to execute a the query against the mainDB and projectDB join. You can either do that in one gigantic "union" query, or by creating a temporary table and inserting the data into that temporary table, and then selecting from the temp table at the end of the query.
For you who are curious of how to solve this issue I have found my own solution using some cursors + dynamic and a simple table variable, enjoy.
ALTER PROCEDURE CloudAnalysis as
DECLARE #objcursor cursor
DECLARE #innercursor cursor
DECLARE #userid int
,#maindb nvarchar(100)
,#clientid int
,#name nvarchar(50)
,#projdb nvarchar(100)
,#stat nvarchar(50)
,#sql nvarchar(max)
,#vsql nvarchar(max)
,#rowcount int
DECLARE #result table(userid int,clientid int,maindb nvarchar(100),name nvarchar(50),projdb nvarchar(100),stat nvarchar(50))
SET #objcursor = CURSOR FORWARD_ONLY STATIC FOR SELECT c.id,c.maindb,u.client_id FROM dbo.ClientUsers c join dbo.UserClients u on c.id = u.user_id open #objcursor
FETCH NEXT FROM #objcursor INTO #userid,#maindb,#clientid
WHILE (##FETCH_STATUS=0)
BEGIN
IF (EXISTS (SELECT name
FROM master.dbo.sysdatabases
WHERE ('[' + name + ']' = #maindb
OR name = #maindb)))
BEGIN
set #sql = N'SELECT #name = c.name,#projdb=c.ProjectDBName FROM ' + #maindb + '.dbo.CLIENT c WHERE c.id = ' + cast(#clientid as nvarchar)
EXECUTE sp_executesql #sql, N'#name NVARCHAR(50) OUTPUT,#projdb NVARCHAR(100) OUTPUT',
#name = #name OUTPUT
,#projdb = #projdb OUTPUT
SELECT #rowcount = ##ROWCOUNT
IF #rowcount > 0
BEGIN
--print ' client: ' + cast(#clientid as nvarchar)+
--':' + #name + ' projdb: ' + #projdb
IF (EXISTS (SELECT name
FROM master.dbo.sysdatabases
WHERE ('[' + name + ']' = #projdb
OR name = #projdb)))
BEGIN
SET #sql = N'SELECT #stat = j.stat FROM ' + #projdb + '.dbo.JournalTransaction j'
EXECUTE sp_executesql #sql
,N'#stat NVARCHAR(50) OUTPUT'
,#stat = #stat OUTPUT
END
INSERT INTO #result (userid,clientid,maindb,name,projdb,stat)
VALUES (#userid,#clientid,#maindb,#name,#projdb,#stat)
END
END
FETCH NEXT FROM #objcursor INTO #userid,#maindb,#clientid
END
CLOSE #objcursor
DEALLOCATE #objcursor
SELECT * FROM #result
SELECT name FROM sys.databases -- this can list all database name in the server
user database
SELECT * FROM INFORMATION_SCHEMA.TABLES
-- these two line can list the table for one particular database
But how can I output the results like below?
Database Table
--------- -------------
db1 t1
db1 t2
db2 t1
... ...
sp_msforeachdb 'select "?" AS db, * from [?].sys.tables'
Here is a stored procedure I use constantly to list all my tables ordered by the space used by them in the database.
GO
/****** Object: StoredProcedure [dbo].[dba_SpaceUsed] Script Date: 03/16/2010 15:09:55 ******/
SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO
CREATE PROC [dbo].[dba_SpaceUsed]
#SourceDB varchar ( 128 ) = null -- Optional database name
-- If omitted, the current database is reported.
, #SortBy char(1) = 'S' -- N for name, S for Size
-- T for table name
AS
SET NOCOUNT ON
DECLARE #sql nvarchar (4000)
IF #SourceDB IS NULL BEGIN
SET #SourceDB = DB_NAME () -- The current DB
END
--------------------------------------------------------
-- Create and fill a list of the tables in the database.
CREATE TABLE #Tables ( [schema] sysname
, TabName sysname )
SELECT #sql = 'insert #tables ([schema], [TabName])
select TABLE_SCHEMA, TABLE_NAME
from ['+ #SourceDB +'].INFORMATION_SCHEMA.TABLES
where TABLE_TYPE = ''BASE TABLE'''
EXEC (#sql)
---------------------------------------------------------------
-- #TabSpaceTxt Holds the results of sp_spaceused.
-- It Doesn't have Schema Info!
CREATE TABLE #TabSpaceTxt (
TabName sysname
, [Rows] varchar (11)
, Reserved varchar (18)
, Data varchar (18)
, Index_Size varchar ( 18 )
, Unused varchar ( 18 )
)
---------------------------------------------------------------
-- The result table, with numeric results and Schema name.
CREATE TABLE #TabSpace ( [Schema] sysname
, TabName sysname
, [Rows] bigint
, ReservedMB numeric(18,3)
, DataMB numeric(18,3)
, Index_SizeMB numeric(18,3)
, UnusedMB numeric(18,3)
)
DECLARE #Tab sysname -- table name
, #Sch sysname -- owner,schema
DECLARE TableCursor CURSOR FOR
SELECT [SCHEMA], TabNAME
FROM #tables
OPEN TableCursor;
FETCH TableCursor into #Sch, #Tab;
WHILE ##FETCH_STATUS = 0 BEGIN
SELECT #sql = 'exec [' + #SourceDB
+ ']..sp_executesql N''insert #TabSpaceTxt exec sp_spaceused '
+ '''''[' + #Sch + '].[' + #Tab + ']' + '''''''';
Delete from #TabSpaceTxt; -- Stores 1 result at a time
EXEC (#sql);
INSERT INTO #TabSpace
SELECT #Sch
, [TabName]
, convert(bigint, rows)
, convert(numeric(18,3), convert(numeric(18,3),
left(reserved, len(reserved)-3)) / 1024.0)
ReservedMB
, convert(numeric(18,3), convert(numeric(18,3),
left(data, len(data)-3)) / 1024.0) DataMB
, convert(numeric(18,3), convert(numeric(18,3),
left(index_size, len(index_size)-3)) / 1024.0)
Index_SizeMB
, convert(numeric(18,3), convert(numeric(18,3),
left(unused, len([Unused])-3)) / 1024.0)
[UnusedMB]
FROM #TabSpaceTxt;
FETCH TableCursor into #Sch, #Tab;
END;
CLOSE TableCursor;
DEALLOCATE TableCursor;
-----------------------------------------------------
-- Caller specifies sort, Default is size
IF #SortBy = 'N' -- Use Schema then Table Name
SELECT * FROM #TabSpace
ORDER BY [Schema] asc, [TabName] asc
ELSE IF #SortBy = 'T' -- Table name, then schema
SELECT * FROM #TabSpace
ORDER BY [TabName] asc, [Schema] asc
ELSE -- S, NULL, or whatever get's the default
SELECT * FROM #TabSpace
ORDER BY ReservedMB desc
;
DROP TABLE #Tables
DROP TABLE #TabSpaceTxt
DROP TABLE #TabSpace
--Thanks to Andrew Novick
if you need one result set, try this:
DECLARE #AllTables table (DatabaseName sysname, TableName sysname)
DECLARE #Current sysname
,#SQL1 varchar(500)
,#SQL2 varchar(500)
,#SQL3 varchar(500)
,#SQL varchar(1500)
SELECT TOP 1 #Current=Name FROM sys.databases Order By Name
SET #SQL1='select db.name, t.TABLE_NAME from '
SET #SQL2='.sys.databases db inner join '
SET #SQL3='.INFORMATION_SCHEMA.TABLES t on db.name = t.TABLE_CATALOG'
WHILE #Current IS NOT NULL
BEGIN
SET #SQL=#SQL1+#Current+#SQL2+#Current+#SQL3
INSERT INTO #AllTables
EXEC (#SQL)
SELECT TOP 1 #Current=Name FROM sys.databases WHERE Name>#Current Order By Name
IF ##ROWCOUNT=0 BREAK
END
SELECT * FROM #AllTables ORDER BY DatabaseName,TableName
If you're lucky enough to still be using sql2000:
CREATE TABLE #AllTables (DatabaseName sysname, TableName sysname)
DECLARE #Current sysname
,#SQL1 varchar(500)
,#SQL2 varchar(500)
,#SQL3 varchar(500)
,#SQL varchar(1500)
SELECT TOP 1 #Current=Name FROM sysdatabases Order By Name
SET #SQL1='select db.name, t.TABLE_NAME from '
SET #SQL2='sysdatabases db inner join '
SET #SQL3='.INFORMATION_SCHEMA.TABLES t on db.name = t.TABLE_CATALOG'
WHILE #Current IS NOT NULL
BEGIN
SET #SQL=#SQL1+#SQL2+#Current+#SQL3
--PRINT #SQL
SET NOCOUNT ON
INSERT INTO #AllTables
EXEC (#SQL)
SET NOCOUNT OFF
SELECT TOP 1 #Current=Name FROM sysdatabases WHERE Name>#Current Order By Name
IF ##ROWCOUNT=0 BREAK
END
SELECT * FROM #AllTables
--where TableName = 'at_errorlog'
ORDER BY DatabaseName,TableName
DROP TABLE #AllTables
select table_name from user_tables;
Using MSSQL2005, can I truncate a table with a foreign key constraint if I first truncate the child table (the table with the primary key of the FK relationship)?
I know that I can either
Use a DELETE without a where clause and then RESEED the identity (or)
Remove the FK, truncate the table, and recreate the FK.
I thought that as long as I truncated the child table before the parent, I'd be okay without doing either of the options above, but I'm getting this error:
Cannot truncate table 'TableName' because it is being referenced by a FOREIGN KEY constraint.
DELETE FROM TABLENAME
DBCC CHECKIDENT ('DATABASENAME.dbo.TABLENAME', RESEED, 0)
Note that this isn't probably what you'd want if you have millions+ of records, as it's very slow.
Correct; you cannot truncate a table which has an FK constraint on it.
Typically my process for this is:
Drop the constraints
Trunc the table
Recreate the constraints.
(All in a transaction, of course.)
Of course, this only applies if the child has already been truncated. Otherwise I go a different route, dependent entirely on what my data looks like. (Too many variables to get into here.)
The original poster determined WHY this is the case; see this answer for more details.
Because TRUNCATE TABLE is a DDL command, it cannot check to see whether the records in the table are being referenced by a record in the child table.
This is why DELETE works and TRUNCATE TABLE doesn't: because the database is able to make sure that it isn't being referenced by another record.
Without ALTER TABLE
-- Delete all records
DELETE FROM [TableName]
-- Set current ID to "1"
-- If table already contains data, use "0"
-- If table is empty and never insert data, use "1"
-- Use SP https://github.com/reduardo7/TableTruncate
DBCC CHECKIDENT ([TableName], RESEED, 0)
As Stored Procedure
https://github.com/reduardo7/TableTruncate
Note that this isn't probably what you'd want if you have millions+ of records, as it's very slow.
The solution #denver_citizen provided above did not work for me, but I liked the spirit of it so I modified a few things :
made it a stored procedure
changed the way the foreign keys are populated and recreated
the original script truncates all referenced tables, this can cause foreign key violation error when the referenced table has other foreign key references. This script truncates only the table specified as parameter. It is up to the user, to call this stored procedure multiple times on all tables in the correct order
For the benefit of the public here is the updated script :
CREATE PROCEDURE [dbo].[truncate_non_empty_table]
#TableToTruncate VARCHAR(64)
AS
BEGIN
SET NOCOUNT ON
-- GLOBAL VARIABLES
DECLARE #i int
DECLARE #Debug bit
DECLARE #Recycle bit
DECLARE #Verbose bit
DECLARE #TableName varchar(80)
DECLARE #ColumnName varchar(80)
DECLARE #ReferencedTableName varchar(80)
DECLARE #ReferencedColumnName varchar(80)
DECLARE #ConstraintName varchar(250)
DECLARE #CreateStatement varchar(max)
DECLARE #DropStatement varchar(max)
DECLARE #TruncateStatement varchar(max)
DECLARE #CreateStatementTemp varchar(max)
DECLARE #DropStatementTemp varchar(max)
DECLARE #TruncateStatementTemp varchar(max)
DECLARE #Statement varchar(max)
-- 1 = Will not execute statements
SET #Debug = 0
-- 0 = Will not create or truncate storage table
-- 1 = Will create or truncate storage table
SET #Recycle = 0
-- 1 = Will print a message on every step
set #Verbose = 1
SET #i = 1
SET #CreateStatement = 'ALTER TABLE [dbo].[<tablename>] WITH NOCHECK ADD CONSTRAINT [<constraintname>] FOREIGN KEY([<column>]) REFERENCES [dbo].[<reftable>] ([<refcolumn>])'
SET #DropStatement = 'ALTER TABLE [dbo].[<tablename>] DROP CONSTRAINT [<constraintname>]'
SET #TruncateStatement = 'TRUNCATE TABLE [<tablename>]'
-- Drop Temporary tables
IF OBJECT_ID('tempdb..#FKs') IS NOT NULL
DROP TABLE #FKs
-- GET FKs
SELECT ROW_NUMBER() OVER (ORDER BY OBJECT_NAME(parent_object_id), clm1.name) as ID,
OBJECT_NAME(constraint_object_id) as ConstraintName,
OBJECT_NAME(parent_object_id) as TableName,
clm1.name as ColumnName,
OBJECT_NAME(referenced_object_id) as ReferencedTableName,
clm2.name as ReferencedColumnName
INTO #FKs
FROM sys.foreign_key_columns fk
JOIN sys.columns clm1
ON fk.parent_column_id = clm1.column_id
AND fk.parent_object_id = clm1.object_id
JOIN sys.columns clm2
ON fk.referenced_column_id = clm2.column_id
AND fk.referenced_object_id= clm2.object_id
--WHERE OBJECT_NAME(parent_object_id) not in ('//tables that you do not wont to be truncated')
WHERE OBJECT_NAME(referenced_object_id) = #TableToTruncate
ORDER BY OBJECT_NAME(parent_object_id)
-- Prepare Storage Table
IF Not EXISTS(SELECT 1 FROM INFORMATION_SCHEMA.TABLES WHERE TABLE_NAME = 'Internal_FK_Definition_Storage')
BEGIN
IF #Verbose = 1
PRINT '1. Creating Process Specific Tables...'
-- CREATE STORAGE TABLE IF IT DOES NOT EXISTS
CREATE TABLE [Internal_FK_Definition_Storage]
(
ID int not null identity(1,1) primary key,
FK_Name varchar(250) not null,
FK_CreationStatement varchar(max) not null,
FK_DestructionStatement varchar(max) not null,
Table_TruncationStatement varchar(max) not null
)
END
ELSE
BEGIN
IF #Recycle = 0
BEGIN
IF #Verbose = 1
PRINT '1. Truncating Process Specific Tables...'
-- TRUNCATE TABLE IF IT ALREADY EXISTS
TRUNCATE TABLE [Internal_FK_Definition_Storage]
END
ELSE
PRINT '1. Process specific table will be recycled from previous execution...'
END
IF #Recycle = 0
BEGIN
IF #Verbose = 1
PRINT '2. Backing up Foreign Key Definitions...'
-- Fetch and persist FKs
WHILE (#i <= (SELECT MAX(ID) FROM #FKs))
BEGIN
SET #ConstraintName = (SELECT ConstraintName FROM #FKs WHERE ID = #i)
SET #TableName = (SELECT TableName FROM #FKs WHERE ID = #i)
SET #ColumnName = (SELECT ColumnName FROM #FKs WHERE ID = #i)
SET #ReferencedTableName = (SELECT ReferencedTableName FROM #FKs WHERE ID = #i)
SET #ReferencedColumnName = (SELECT ReferencedColumnName FROM #FKs WHERE ID = #i)
SET #DropStatementTemp = REPLACE(REPLACE(#DropStatement,'<tablename>',#TableName),'<constraintname>',#ConstraintName)
SET #CreateStatementTemp = REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(#CreateStatement,'<tablename>',#TableName),'<column>',#ColumnName),'<constraintname>',#ConstraintName),'<reftable>',#ReferencedTableName),'<refcolumn>',#ReferencedColumnName)
SET #TruncateStatementTemp = REPLACE(#TruncateStatement,'<tablename>',#TableName)
INSERT INTO [Internal_FK_Definition_Storage]
SELECT #ConstraintName, #CreateStatementTemp, #DropStatementTemp, #TruncateStatementTemp
SET #i = #i + 1
IF #Verbose = 1
PRINT ' > Backing up [' + #ConstraintName + '] from [' + #TableName + ']'
END
END
ELSE
PRINT '2. Backup up was recycled from previous execution...'
IF #Verbose = 1
PRINT '3. Dropping Foreign Keys...'
-- DROP FOREING KEYS
SET #i = 1
WHILE (#i <= (SELECT MAX(ID) FROM [Internal_FK_Definition_Storage]))
BEGIN
SET #ConstraintName = (SELECT FK_Name FROM [Internal_FK_Definition_Storage] WHERE ID = #i)
SET #Statement = (SELECT FK_DestructionStatement FROM [Internal_FK_Definition_Storage] WITH (NOLOCK) WHERE ID = #i)
IF #Debug = 1
PRINT #Statement
ELSE
EXEC(#Statement)
SET #i = #i + 1
IF #Verbose = 1
PRINT ' > Dropping [' + #ConstraintName + ']'
END
IF #Verbose = 1
PRINT '4. Truncating Tables...'
-- TRUNCATE TABLES
-- SzP: commented out as the tables to be truncated might also contain tables that has foreign keys
-- to resolve this the stored procedure should be called recursively, but I dont have the time to do it...
/*
SET #i = 1
WHILE (#i <= (SELECT MAX(ID) FROM [Internal_FK_Definition_Storage]))
BEGIN
SET #Statement = (SELECT Table_TruncationStatement FROM [Internal_FK_Definition_Storage] WHERE ID = #i)
IF #Debug = 1
PRINT #Statement
ELSE
EXEC(#Statement)
SET #i = #i + 1
IF #Verbose = 1
PRINT ' > ' + #Statement
END
*/
IF #Verbose = 1
PRINT ' > TRUNCATE TABLE [' + #TableToTruncate + ']'
IF #Debug = 1
PRINT 'TRUNCATE TABLE [' + #TableToTruncate + ']'
ELSE
EXEC('TRUNCATE TABLE [' + #TableToTruncate + ']')
IF #Verbose = 1
PRINT '5. Re-creating Foreign Keys...'
-- CREATE FOREING KEYS
SET #i = 1
WHILE (#i <= (SELECT MAX(ID) FROM [Internal_FK_Definition_Storage]))
BEGIN
SET #ConstraintName = (SELECT FK_Name FROM [Internal_FK_Definition_Storage] WHERE ID = #i)
SET #Statement = (SELECT FK_CreationStatement FROM [Internal_FK_Definition_Storage] WHERE ID = #i)
IF #Debug = 1
PRINT #Statement
ELSE
EXEC(#Statement)
SET #i = #i + 1
IF #Verbose = 1
PRINT ' > Re-creating [' + #ConstraintName + ']'
END
IF #Verbose = 1
PRINT '6. Process Completed'
END
use the following command after deletion of all rows in that table by using delete statement
delete from tablename
DBCC CHECKIDENT ('tablename', RESEED, 0)
EDIT: Corrected syntax for SQL Server
Well, since I did not find examples of the very simple solution I used, which is:
Drop foreign key;
Truncate table
Recreate foreign key
Here it goes:
1) Find the foreign key name that is causing the failure (for example: FK_PROBLEM_REASON, with field ID, from table TABLE_OWNING_CONSTRAINT)
2) Remove that key from the table:
ALTER TABLE TABLE_OWNING_CONSTRAINT DROP CONSTRAINT FK_PROBLEM_REASON
3) Truncate wanted table
TRUNCATE TABLE TABLE_TO_TRUNCATE
4) Re-add the key to that first table:
ALTER TABLE TABLE_OWNING_CONSTRAINT ADD CONSTRAINT FK_PROBLEM_REASON FOREIGN KEY(ID) REFERENCES TABLE_TO_TRUNCATE (ID)
That's it.
The process is removing foreign key constraint and truncate table
then add constrain by following steps.
This is Just for MySQL
SET FOREIGN_KEY_CHECKS = 0;
truncate table "yourTableName";
SET FOREIGN_KEY_CHECKS = 1;
you can follow this step,
By reseeding table you can delete the data of the table.
delete from table_name
dbcc checkident('table_name',reseed,0)
if some error comes then you have to reseed the primary table.
Here is a script I wrote in order to automate the process. I hope it helps.
SET NOCOUNT ON
-- GLOBAL VARIABLES
DECLARE #i int
DECLARE #Debug bit
DECLARE #Recycle bit
DECLARE #Verbose bit
DECLARE #TableName varchar(80)
DECLARE #ColumnName varchar(80)
DECLARE #ReferencedTableName varchar(80)
DECLARE #ReferencedColumnName varchar(80)
DECLARE #ConstraintName varchar(250)
DECLARE #CreateStatement varchar(max)
DECLARE #DropStatement varchar(max)
DECLARE #TruncateStatement varchar(max)
DECLARE #CreateStatementTemp varchar(max)
DECLARE #DropStatementTemp varchar(max)
DECLARE #TruncateStatementTemp varchar(max)
DECLARE #Statement varchar(max)
-- 1 = Will not execute statements
SET #Debug = 0
-- 0 = Will not create or truncate storage table
-- 1 = Will create or truncate storage table
SET #Recycle = 0
-- 1 = Will print a message on every step
set #Verbose = 1
SET #i = 1
SET #CreateStatement = 'ALTER TABLE [dbo].[<tablename>] WITH NOCHECK ADD CONSTRAINT [<constraintname>] FOREIGN KEY([<column>]) REFERENCES [dbo].[<reftable>] ([<refcolumn>])'
SET #DropStatement = 'ALTER TABLE [dbo].[<tablename>] DROP CONSTRAINT [<constraintname>]'
SET #TruncateStatement = 'TRUNCATE TABLE [<tablename>]'
-- Drop Temporary tables
DROP TABLE #FKs
-- GET FKs
SELECT ROW_NUMBER() OVER (ORDER BY OBJECT_NAME(parent_object_id), clm1.name) as ID,
OBJECT_NAME(constraint_object_id) as ConstraintName,
OBJECT_NAME(parent_object_id) as TableName,
clm1.name as ColumnName,
OBJECT_NAME(referenced_object_id) as ReferencedTableName,
clm2.name as ReferencedColumnName
INTO #FKs
FROM sys.foreign_key_columns fk
JOIN sys.columns clm1
ON fk.parent_column_id = clm1.column_id
AND fk.parent_object_id = clm1.object_id
JOIN sys.columns clm2
ON fk.referenced_column_id = clm2.column_id
AND fk.referenced_object_id= clm2.object_id
WHERE OBJECT_NAME(parent_object_id) not in ('//tables that you do not wont to be truncated')
ORDER BY OBJECT_NAME(parent_object_id)
-- Prepare Storage Table
IF Not EXISTS(SELECT 1 FROM INFORMATION_SCHEMA.TABLES WHERE TABLE_NAME = 'Internal_FK_Definition_Storage')
BEGIN
IF #Verbose = 1
PRINT '1. Creating Process Specific Tables...'
-- CREATE STORAGE TABLE IF IT DOES NOT EXISTS
CREATE TABLE [Internal_FK_Definition_Storage]
(
ID int not null identity(1,1) primary key,
FK_Name varchar(250) not null,
FK_CreationStatement varchar(max) not null,
FK_DestructionStatement varchar(max) not null,
Table_TruncationStatement varchar(max) not null
)
END
ELSE
BEGIN
IF #Recycle = 0
BEGIN
IF #Verbose = 1
PRINT '1. Truncating Process Specific Tables...'
-- TRUNCATE TABLE IF IT ALREADY EXISTS
TRUNCATE TABLE [Internal_FK_Definition_Storage]
END
ELSE
PRINT '1. Process specific table will be recycled from previous execution...'
END
IF #Recycle = 0
BEGIN
IF #Verbose = 1
PRINT '2. Backing up Foreign Key Definitions...'
-- Fetch and persist FKs
WHILE (#i <= (SELECT MAX(ID) FROM #FKs))
BEGIN
SET #ConstraintName = (SELECT ConstraintName FROM #FKs WHERE ID = #i)
SET #TableName = (SELECT TableName FROM #FKs WHERE ID = #i)
SET #ColumnName = (SELECT ColumnName FROM #FKs WHERE ID = #i)
SET #ReferencedTableName = (SELECT ReferencedTableName FROM #FKs WHERE ID = #i)
SET #ReferencedColumnName = (SELECT ReferencedColumnName FROM #FKs WHERE ID = #i)
SET #DropStatementTemp = REPLACE(REPLACE(#DropStatement,'<tablename>',#TableName),'<constraintname>',#ConstraintName)
SET #CreateStatementTemp = REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(#CreateStatement,'<tablename>',#TableName),'<column>',#ColumnName),'<constraintname>',#ConstraintName),'<reftable>',#ReferencedTableName),'<refcolumn>',#ReferencedColumnName)
SET #TruncateStatementTemp = REPLACE(#TruncateStatement,'<tablename>',#TableName)
INSERT INTO [Internal_FK_Definition_Storage]
SELECT #ConstraintName, #CreateStatementTemp, #DropStatementTemp, #TruncateStatementTemp
SET #i = #i + 1
IF #Verbose = 1
PRINT ' > Backing up [' + #ConstraintName + '] from [' + #TableName + ']'
END
END
ELSE
PRINT '2. Backup up was recycled from previous execution...'
IF #Verbose = 1
PRINT '3. Dropping Foreign Keys...'
-- DROP FOREING KEYS
SET #i = 1
WHILE (#i <= (SELECT MAX(ID) FROM [Internal_FK_Definition_Storage]))
BEGIN
SET #ConstraintName = (SELECT FK_Name FROM [Internal_FK_Definition_Storage] WHERE ID = #i)
SET #Statement = (SELECT FK_DestructionStatement FROM [Internal_FK_Definition_Storage] WITH (NOLOCK) WHERE ID = #i)
IF #Debug = 1
PRINT #Statement
ELSE
EXEC(#Statement)
SET #i = #i + 1
IF #Verbose = 1
PRINT ' > Dropping [' + #ConstraintName + ']'
END
IF #Verbose = 1
PRINT '4. Truncating Tables...'
-- TRUNCATE TABLES
SET #i = 1
WHILE (#i <= (SELECT MAX(ID) FROM [Internal_FK_Definition_Storage]))
BEGIN
SET #Statement = (SELECT Table_TruncationStatement FROM [Internal_FK_Definition_Storage] WHERE ID = #i)
IF #Debug = 1
PRINT #Statement
ELSE
EXEC(#Statement)
SET #i = #i + 1
IF #Verbose = 1
PRINT ' > ' + #Statement
END
IF #Verbose = 1
PRINT '5. Re-creating Foreign Keys...'
-- CREATE FOREING KEYS
SET #i = 1
WHILE (#i <= (SELECT MAX(ID) FROM [Internal_FK_Definition_Storage]))
BEGIN
SET #ConstraintName = (SELECT FK_Name FROM [Internal_FK_Definition_Storage] WHERE ID = #i)
SET #Statement = (SELECT FK_CreationStatement FROM [Internal_FK_Definition_Storage] WHERE ID = #i)
IF #Debug = 1
PRINT #Statement
ELSE
EXEC(#Statement)
SET #i = #i + 1
IF #Verbose = 1
PRINT ' > Re-creating [' + #ConstraintName + ']'
END
IF #Verbose = 1
PRINT '6. Process Completed'
#denver_citizen and #Peter Szanto's answers didn't quite work for me, but I modified them to account for:
Composite Keys
On Delete and On Update actions
Checking the index when re-adding
Schemas other than dbo
Multiple tables at once
DECLARE #Debug bit = 0;
-- List of tables to truncate
select
SchemaName, Name
into #tables
from (values
('schema', 'table')
,('schema2', 'table2')
) as X(SchemaName, Name)
BEGIN TRANSACTION TruncateTrans;
with foreignKeys AS (
SELECT
SCHEMA_NAME(fk.schema_id) as SchemaName
,fk.Name as ConstraintName
,OBJECT_NAME(fk.parent_object_id) as TableName
,SCHEMA_NAME(t.SCHEMA_ID) as ReferencedSchemaName
,OBJECT_NAME(fk.referenced_object_id) as ReferencedTableName
,fc.constraint_column_id
,COL_NAME(fk.parent_object_id, fc.parent_column_id) AS ColumnName
,COL_NAME(fk.referenced_object_id, fc.referenced_column_id) as ReferencedColumnName
,fk.delete_referential_action_desc
,fk.update_referential_action_desc
FROM sys.foreign_keys AS fk
JOIN sys.foreign_key_columns AS fc
ON fk.object_id = fc.constraint_object_id
JOIN #tables tbl
ON OBJECT_NAME(fc.referenced_object_id) = tbl.Name
JOIN sys.tables t on OBJECT_NAME(t.object_id) = tbl.Name
and SCHEMA_NAME(t.schema_id) = tbl.SchemaName
and t.OBJECT_ID = fc.referenced_object_id
)
select
quotename(fk.ConstraintName) AS ConstraintName
,quotename(fk.SchemaName) + '.' + quotename(fk.TableName) AS TableName
,quotename(fk.ReferencedSchemaName) + '.' + quotename(fk.ReferencedTableName) AS ReferencedTableName
,replace(fk.delete_referential_action_desc, '_', ' ') AS DeleteAction
,replace(fk.update_referential_action_desc, '_', ' ') AS UpdateAction
,STUFF((
SELECT ',' + quotename(fk2.ColumnName)
FROM foreignKeys fk2
WHERE fk2.ConstraintName = fk.ConstraintName and fk2.SchemaName = fk.SchemaName
ORDER BY fk2.constraint_column_id
FOR XML PATH('')
),1,1,'') AS ColumnNames
,STUFF((
SELECT ',' + quotename(fk2.ReferencedColumnName)
FROM foreignKeys fk2
WHERE fk2.ConstraintName = fk.ConstraintName and fk2.SchemaName = fk.SchemaName
ORDER BY fk2.constraint_column_id
FOR XML PATH('')
),1,1,'') AS ReferencedColumnNames
into #FKs
from foreignKeys fk
GROUP BY fk.SchemaName, fk.ConstraintName, fk.TableName, fk.ReferencedSchemaName, fk.ReferencedTableName, fk.delete_referential_action_desc, fk.update_referential_action_desc
-- Drop FKs
select
identity(int,1,1) as ID,
'ALTER TABLE ' + fk.TableName + ' DROP CONSTRAINT ' + fk.ConstraintName AS script
into #scripts
from #FKs fk
-- Truncate
insert into #scripts
select distinct
'TRUNCATE TABLE ' + quotename(tbl.SchemaName) + '.' + quotename(tbl.Name) AS script
from #tables tbl
-- Recreate
insert into #scripts
select
'ALTER TABLE ' + fk.TableName +
' WITH CHECK ADD CONSTRAINT ' + fk.ConstraintName +
' FOREIGN KEY ('+ fk.ColumnNames +')' +
' REFERENCES ' + fk.ReferencedTableName +' ('+ fk.ReferencedColumnNames +')' +
' ON DELETE ' + fk.DeleteAction COLLATE Latin1_General_CI_AS_KS_WS + ' ON UPDATE ' + fk.UpdateAction COLLATE Latin1_General_CI_AS_KS_WS AS script
from #FKs fk
DECLARE #script nvarchar(MAX);
DECLARE curScripts CURSOR FOR
select script
from #scripts
order by ID
OPEN curScripts
WHILE 1=1 BEGIN
FETCH NEXT FROM curScripts INTO #script
IF ##FETCH_STATUS != 0 BREAK;
print #script;
IF #Debug = 0
EXEC (#script);
END
CLOSE curScripts
DEALLOCATE curScripts
drop table #scripts
drop table #FKs
drop table #tables
COMMIT TRANSACTION TruncateTrans;
You cannot truncate a table if you don't drop the constraints. A disable also doesn't work. you need to Drop everything. i've made a script that drop all constrainsts and then recreate then.
Be sure to wrap it in a transaction ;)
SET NOCOUNT ON
GO
DECLARE #table TABLE(
RowId INT PRIMARY KEY IDENTITY(1, 1),
ForeignKeyConstraintName NVARCHAR(200),
ForeignKeyConstraintTableSchema NVARCHAR(200),
ForeignKeyConstraintTableName NVARCHAR(200),
ForeignKeyConstraintColumnName NVARCHAR(200),
PrimaryKeyConstraintName NVARCHAR(200),
PrimaryKeyConstraintTableSchema NVARCHAR(200),
PrimaryKeyConstraintTableName NVARCHAR(200),
PrimaryKeyConstraintColumnName NVARCHAR(200)
)
INSERT INTO #table(ForeignKeyConstraintName, ForeignKeyConstraintTableSchema, ForeignKeyConstraintTableName, ForeignKeyConstraintColumnName)
SELECT
U.CONSTRAINT_NAME,
U.TABLE_SCHEMA,
U.TABLE_NAME,
U.COLUMN_NAME
FROM
INFORMATION_SCHEMA.KEY_COLUMN_USAGE U
INNER JOIN INFORMATION_SCHEMA.TABLE_CONSTRAINTS C
ON U.CONSTRAINT_NAME = C.CONSTRAINT_NAME
WHERE
C.CONSTRAINT_TYPE = 'FOREIGN KEY'
UPDATE #table SET
PrimaryKeyConstraintName = UNIQUE_CONSTRAINT_NAME
FROM
#table T
INNER JOIN INFORMATION_SCHEMA.REFERENTIAL_CONSTRAINTS R
ON T.ForeignKeyConstraintName = R.CONSTRAINT_NAME
UPDATE #table SET
PrimaryKeyConstraintTableSchema = TABLE_SCHEMA,
PrimaryKeyConstraintTableName = TABLE_NAME
FROM #table T
INNER JOIN INFORMATION_SCHEMA.TABLE_CONSTRAINTS C
ON T.PrimaryKeyConstraintName = C.CONSTRAINT_NAME
UPDATE #table SET
PrimaryKeyConstraintColumnName = COLUMN_NAME
FROM #table T
INNER JOIN INFORMATION_SCHEMA.KEY_COLUMN_USAGE U
ON T.PrimaryKeyConstraintName = U.CONSTRAINT_NAME
--DROP CONSTRAINT:
DECLARE #dynSQL varchar(MAX);
DECLARE cur CURSOR FOR
SELECT
'
ALTER TABLE [' + ForeignKeyConstraintTableSchema + '].[' + ForeignKeyConstraintTableName + ']
DROP CONSTRAINT ' + ForeignKeyConstraintName + '
'
FROM
#table
OPEN cur
FETCH cur into #dynSQL
WHILE ##FETCH_STATUS = 0
BEGIN
exec(#dynSQL)
print #dynSQL
FETCH cur into #dynSQL
END
CLOSE cur
DEALLOCATE cur
---------------------
--HERE GOES YOUR TRUNCATES!!!!!
--HERE GOES YOUR TRUNCATES!!!!!
--HERE GOES YOUR TRUNCATES!!!!!
truncate table your_table
--HERE GOES YOUR TRUNCATES!!!!!
--HERE GOES YOUR TRUNCATES!!!!!
--HERE GOES YOUR TRUNCATES!!!!!
---------------------
--ADD CONSTRAINT:
DECLARE cur2 CURSOR FOR
SELECT
'
ALTER TABLE [' + ForeignKeyConstraintTableSchema + '].[' + ForeignKeyConstraintTableName + ']
ADD CONSTRAINT ' + ForeignKeyConstraintName + ' FOREIGN KEY(' + ForeignKeyConstraintColumnName + ') REFERENCES [' + PrimaryKeyConstraintTableSchema + '].[' + PrimaryKeyConstraintTableName + '](' + PrimaryKeyConstraintColumnName + ')
'
FROM
#table
OPEN cur2
FETCH cur2 into #dynSQL
WHILE ##FETCH_STATUS = 0
BEGIN
exec(#dynSQL)
print #dynSQL
FETCH cur2 into #dynSQL
END
CLOSE cur2
DEALLOCATE cur2
If I understand correctly, what you want to do is to have a clean environment to be set up for DB involving integration tests.
My approach here would be to drop the whole schema and recreate it later.
Reasons:
You probably already have a "create schema" script. Re-using it for test isolation is easy.
Creating a schema is pretty quick.
With that approach, it is pretty easy to set up your script to have each fixture create a NEW schema (with a temporary name), and then you can start running test-fixtures in parallel, making the slowest part of your test suite much faster.
Found elsewhere on the web
EXEC sp_MSForEachTable 'ALTER TABLE ? NOCHECK CONSTRAINT ALL'
EXEC sp_MSForEachTable 'ALTER TABLE ? DISABLE TRIGGER ALL'
-- EXEC sp_MSForEachTable 'DELETE FROM ?' -- Uncomment to execute
EXEC sp_MSForEachTable 'ALTER TABLE ? CHECK CONSTRAINT ALL'
EXEC sp_MSForEachTable 'ALTER TABLE ? ENABLE TRIGGER ALL'
I write the following ways and tried to parameterized them, so you can Run them in a Query document Or Make a useful SP with them easily.
A) Delete
If your table has not millions of records this works good and hasn't any Alter commands:
---------------------------------------------------------------
------------------- Just Fill Parameters Value ----------------
---------------------------------------------------------------
DECLARE #DbName AS NVARCHAR(30) = 'MyDb' --< Db Name
DECLARE #Schema AS NVARCHAR(30) = 'dbo' --< Schema
DECLARE #TableName AS NVARCHAR(30) = 'Book' --< Table Name
------------------ /Just Fill Parameters Value ----------------
DECLARE #Query AS NVARCHAR(500) = 'Delete FROM ' + #TableName
EXECUTE sp_executesql #Query
SET #Query=#DbName+'.'+#Schema+'.'+#TableName
DBCC CHECKIDENT (#Query,RESEED, 0)
In above answer of mine the method of resolve the mentioned problem in the question is based on #s15199d answer.
B) Truncate
If your table has millions of records or you hasn't any problem with Alter command in your codes, then use this one:
-- Book Student
--
-- | BookId | Field1 | | StudentId | BookId |
-- --------------------- ------------------------
-- | 1 | A | | 2 | 1 |
-- | 2 | B | | 1 | 1 |
-- | 3 | C | | 2 | 3 |
---------------------------------------------------------------
------------------- Just Fill Parameters Value ----------------
---------------------------------------------------------------
DECLARE #DbName AS NVARCHAR(30) = 'MyDb'
DECLARE #Schema AS NVARCHAR(30) = 'dbo'
DECLARE #TableName_ToTruncate AS NVARCHAR(30) = 'Book'
DECLARE #TableName_OfOwnerOfConstraint AS NVARCHAR(30) = 'Student' --< Decelations About FK_Book_Constraint
DECLARE #Ref_ColumnName_In_TableName_ToTruncate AS NVARCHAR(30) = 'BookId' --< Decelations About FK_Book_Constraint
DECLARE #FK_ColumnName_In_TableOfOwnerOfConstraint AS NVARCHAR(30) = 'Fk_BookId' --< Decelations About FK_Book_Constraint
DECLARE #FK_ConstraintName AS NVARCHAR(30) = 'FK_Book_Constraint' --< Decelations About FK_Book_Constraint
------------------ /Just Fill Parameters Value ----------------
DECLARE #Query AS NVARCHAR(2000)
SET #Query= 'ALTER TABLE '+#TableName_OfOwnerOfConstraint+' DROP CONSTRAINT '+#FK_ConstraintName
EXECUTE sp_executesql #Query
SET #Query= 'Truncate Table '+ #TableName_ToTruncate
EXECUTE sp_executesql #Query
SET #Query= 'ALTER TABLE '+#TableName_OfOwnerOfConstraint+' ADD CONSTRAINT '+#FK_ConstraintName+' FOREIGN KEY('+#FK_ColumnName_In_TableOfOwnerOfConstraint+') REFERENCES '+#TableName_ToTruncate+'('+#Ref_ColumnName_In_TableName_ToTruncate+')'
EXECUTE sp_executesql #Query
In above answer of mine the method of resolve the mentioned problem in the question is based on #LauroWolffValenteSobrinho answer.
If you have more than one CONSTRAINT then you should append its codes like me to the above query
Also you can change the above code base #SerjSagan answer to disable an enable the constraint
truncate did not work for me, delete + reseed is the best way out.
In case there are some of you out there who need to iterate over huge number of tables to perform delete + reseed, you might run into issues with some tables which does not have an identity column, the following code checks if identity column exist before attempting to reseed
EXEC ('DELETE FROM [schemaName].[tableName]')
IF EXISTS (Select * from sys.identity_columns where object_name(object_id) = 'tableName')
BEGIN
EXEC ('DBCC CHECKIDENT ([schemaName.tableName], RESEED, 0)')
END
For MS SQL, at least the newer versions, you can just disable the constrains with code like this:
ALTER TABLE Orders
NOCHECK CONSTRAINT [FK_dbo.Orders_dbo.Customers_Customer_Id]
GO
TRUNCATE TABLE Customers
GO
ALTER TABLE Orders
WITH CHECK CHECK CONSTRAINT [FK_dbo.Orders_dbo.Customers_Customer_Id]
GO
The only way is to drop foreign keys before doing the truncate. And after truncating the data, you must re-create the indexes.
The following script generates the required SQL for dropping all foreign key constraints.
DECLARE #drop NVARCHAR(MAX) = N'';
SELECT #drop += N'
ALTER TABLE ' + QUOTENAME(cs.name) + '.' + QUOTENAME(ct.name)
+ ' DROP CONSTRAINT ' + QUOTENAME(fk.name) + ';'
FROM sys.foreign_keys AS fk
INNER JOIN sys.tables AS ct
ON fk.parent_object_id = ct.[object_id]
INNER JOIN sys.schemas AS cs
ON ct.[schema_id] = cs.[schema_id];
SELECT #drop
Next, the following script generates the required SQL for re-creating foreign keys.
DECLARE #create NVARCHAR(MAX) = N'';
SELECT #create += N'
ALTER TABLE '
+ QUOTENAME(cs.name) + '.' + QUOTENAME(ct.name)
+ ' ADD CONSTRAINT ' + QUOTENAME(fk.name)
+ ' FOREIGN KEY (' + STUFF((SELECT ',' + QUOTENAME(c.name)
-- get all the columns in the constraint table
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(N''), TYPE).value(N'.[1]', N'nvarchar(max)'), 1, 1, N'')
+ ') REFERENCES ' + QUOTENAME(rs.name) + '.' + QUOTENAME(rt.name)
+ '(' + STUFF((SELECT ',' + QUOTENAME(c.name)
-- get all the referenced columns
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(N''), TYPE).value(N'.[1]', N'nvarchar(max)'), 1, 1, N'') + ');'
FROM sys.foreign_keys AS fk
INNER JOIN sys.tables AS rt -- referenced table
ON fk.referenced_object_id = rt.[object_id]
INNER JOIN sys.schemas AS rs
ON rt.[schema_id] = rs.[schema_id]
INNER JOIN sys.tables AS ct -- constraint table
ON fk.parent_object_id = ct.[object_id]
INNER JOIN sys.schemas AS cs
ON ct.[schema_id] = cs.[schema_id]
WHERE rt.is_ms_shipped = 0 AND ct.is_ms_shipped = 0;
SELECT #create
Run the generated script to drop all foreign keys, truncate tables, and then run the generated script to re-create all foreign keys.
The queries are taken from here.
It's my solution of this issue. I used it for altering PK, but idea the same. Hope this will be useful)
PRINT 'Script starts'
DECLARE #foreign_key_name varchar(255)
DECLARE #keycnt int
DECLARE #foreign_table varchar(255)
DECLARE #foreign_column_1 varchar(255)
DECLARE #foreign_column_2 varchar(255)
DECLARE #primary_table varchar(255)
DECLARE #primary_column_1 varchar(255)
DECLARE #primary_column_2 varchar(255)
DECLARE #TablN varchar(255)
-->> Type the primary table name
SET #TablN = ''
--------------------------------------------------------------------------------------- ------------------------------
--Here will be created the temporary table with all reference FKs
---------------------------------------------------------------------------------------------------------------------
PRINT 'Creating the temporary table'
select cast(f.name as varchar(255)) as foreign_key_name
, r.keycnt
, cast(c.name as varchar(255)) as foreign_table
, cast(fc.name as varchar(255)) as foreign_column_1
, cast(fc2.name as varchar(255)) as foreign_column_2
, cast(p.name as varchar(255)) as primary_table
, cast(rc.name as varchar(255)) as primary_column_1
, cast(rc2.name as varchar(255)) as primary_column_2
into #ConTab
from sysobjects f
inner join sysobjects c on f.parent_obj = c.id
inner join sysreferences r on f.id = r.constid
inner join sysobjects p on r.rkeyid = p.id
inner join syscolumns rc on r.rkeyid = rc.id and r.rkey1 = rc.colid
inner join syscolumns fc on r.fkeyid = fc.id and r.fkey1 = fc.colid
left join syscolumns rc2 on r.rkeyid = rc2.id and r.rkey2 = rc.colid
left join syscolumns fc2 on r.fkeyid = fc2.id and r.fkey2 = fc.colid
where f.type = 'F' and p.name = #TablN
ORDER BY cast(p.name as varchar(255))
---------------------------------------------------------------------------------------------------------------------
--Cursor, below, will drop all reference FKs
---------------------------------------------------------------------------------------------------------------------
DECLARE #CURSOR CURSOR
/*Fill in cursor*/
PRINT 'Cursor 1 starting. All refernce FK will be droped'
SET #CURSOR = CURSOR SCROLL
FOR
select foreign_key_name
, keycnt
, foreign_table
, foreign_column_1
, foreign_column_2
, primary_table
, primary_column_1
, primary_column_2
from #ConTab
OPEN #CURSOR
FETCH NEXT FROM #CURSOR INTO #foreign_key_name, #keycnt, #foreign_table, #foreign_column_1, #foreign_column_2,
#primary_table, #primary_column_1, #primary_column_2
WHILE ##FETCH_STATUS = 0
BEGIN
EXEC ('ALTER TABLE ['+#foreign_table+'] DROP CONSTRAINT ['+#foreign_key_name+']')
FETCH NEXT FROM #CURSOR INTO #foreign_key_name, #keycnt, #foreign_table, #foreign_column_1, #foreign_column_2,
#primary_table, #primary_column_1, #primary_column_2
END
CLOSE #CURSOR
PRINT 'Cursor 1 finished work'
---------------------------------------------------------------------------------------------------------------------
--Here you should provide the chainging script for the primary table
---------------------------------------------------------------------------------------------------------------------
PRINT 'Altering primary table begin'
TRUNCATE TABLE table_name
PRINT 'Altering finished'
---------------------------------------------------------------------------------------------------------------------
--Cursor, below, will add again all reference FKs
--------------------------------------------------------------------------------------------------------------------
PRINT 'Cursor 2 starting. All refernce FK will added'
SET #CURSOR = CURSOR SCROLL
FOR
select foreign_key_name
, keycnt
, foreign_table
, foreign_column_1
, foreign_column_2
, primary_table
, primary_column_1
, primary_column_2
from #ConTab
OPEN #CURSOR
FETCH NEXT FROM #CURSOR INTO #foreign_key_name, #keycnt, #foreign_table, #foreign_column_1, #foreign_column_2,
#primary_table, #primary_column_1, #primary_column_2
WHILE ##FETCH_STATUS = 0
BEGIN
EXEC ('ALTER TABLE [' +#foreign_table+ '] WITH NOCHECK ADD CONSTRAINT [' +#foreign_key_name+ '] FOREIGN KEY(['+#foreign_column_1+'])
REFERENCES [' +#primary_table+'] (['+#primary_column_1+'])')
EXEC ('ALTER TABLE [' +#foreign_table+ '] CHECK CONSTRAINT [' +#foreign_key_name+']')
FETCH NEXT FROM #CURSOR INTO #foreign_key_name, #keycnt, #foreign_table, #foreign_column_1, #foreign_column_2,
#primary_table, #primary_column_1, #primary_column_2
END
CLOSE #CURSOR
PRINT 'Cursor 2 finished work'
---------------------------------------------------------------------------------------------------------------------
PRINT 'Temporary table droping'
drop table #ConTab
PRINT 'Finish'
The following works for me even with FK constraints, and combines the following answers to only drop the specified tables:
Transaction Automatic Rollback
Looping through comma-separated list
Executing Dynamic SQL (with table names from variable)
DELETE and RESEED table (in this thread)
USE [YourDB];
DECLARE #TransactionName varchar(20) = 'stopdropandroll';
BEGIN TRAN #TransactionName;
set xact_abort on; /* automatic rollback https://stackoverflow.com/a/1749788/1037948 */
-- ===== DO WORK // =====
-- dynamic sql placeholder
DECLARE #SQL varchar(300);
-- LOOP: https://stackoverflow.com/a/10031803/1037948
-- list of things to loop
DECLARE #delim char = ';';
DECLARE #foreach varchar(MAX) = 'Table;Names;Separated;By;Delimiter' + #delim + 'AnotherName' + #delim + 'Still Another';
DECLARE #token varchar(MAX);
WHILE len(#foreach) > 0
BEGIN
-- set current loop token
SET #token = left(#foreach, charindex(#delim, #foreach+#delim)-1)
-- ======= DO WORK // ===========
-- dynamic sql (parentheses are required): https://stackoverflow.com/a/989111/1037948
SET #SQL = 'DELETE FROM [' + #token + ']; DBCC CHECKIDENT (''' + #token + ''',RESEED, 0);'; -- https://stackoverflow.com/a/11784890
PRINT #SQL;
EXEC (#SQL);
-- ======= // END WORK ===========
-- continue loop, chopping off token
SET #foreach = stuff(#foreach, 1, charindex(#delim, #foreach+#delim), '')
END
-- ===== // END WORK =====
-- review and commit
SELECT ##TRANCOUNT as TransactionsPerformed, ##ROWCOUNT as LastRowsChanged;
COMMIT TRAN #TransactionName;
Note:
I think it still helps to declare the tables in the order you want them deleted (i.e. kill dependencies first). As seen in this answer, rather than loop specific names you could substitute all tables with
EXEC sp_MSForEachTable 'DELETE FROM ?; DBCC CHECKIDENT (''?'',RESEED, 0);';
If none of these answers worked like in my case do this:
Drop constraints
Set all values to allow nulls
Truncate table
Add constraints that were dropped.
Good luck!
Delete then reset auto-increment:
delete from tablename;
then
ALTER TABLE tablename AUTO_INCREMENT = 1;
In SSMS I had Diagram open showing the Key. After deleting the Key and truncating the file I refreshed then focused back on the Diagram and created an update by clearing then restoring an Identity box. Saving the Diagram brought up a Save dialog box, than a "Changes were made in the database while you where working" dialog box, clicking Yes restored the Key, restoring it from the latched copy in the Diagram.
If you're doing this at any sort of a frequency, heck even on a schedule, I would absolutely, unequivocally never use a DML statement. The cost of writing to the transaction log is just to high, and setting the entire database into SIMPLE recovery mode to truncate one table is ridiculous.
The best way, is unfortunately the hard or laborious way. That being:
Drop constraints
Truncate table
Re-create constraints
My process for doing this involves the following steps:
In SSMS right-click on the table in question, and select View Dependencies
Take note of the tables referenced (if any)
Back in object explorer, expand the Keys node and take note of the foreign keys (if any)
Start scripting (drop / truncate / re-create)
Scripts of this nature should be done within a begin tran and commit tran block.
This is an example for someone that use Entity Framework
Table to be reset: Foo
Another table that depends on: Bar
Constraint Column on table Foo : FooColumn
Constraint Column on table Bar : BarColumn
public override void Down()
{
DropForeignKey("dbo.Bar", "BarColumn", "dbo.Foo");
Sql("TRUNCATE TABLE Foo");
AddForeignKey("dbo.Bar", "BarColumn", "dbo.Foo", "FooColumn", cascadeDelete: true);
}
The following script truncates all foreign key constraints & recreates them:
DECLARE #DROP_CONSTRAINT_SCRIPT VARCHAR(MAX);
DECLARE #CREATE_CONSTRAINT_SCRIPT VARCHAR(MAX);
SET #DROP_CONSTRAINT_SCRIPT='';
SET #CREATE_CONSTRAINT_SCRIPT='';
SELECT #DROP_CONSTRAINT_SCRIPT=#DROP_CONSTRAINT_SCRIPT + 'ALTER TABLE '+FK_Table+'
DROP CONSTRAINT '+FK_Name+';
',
#CREATE_CONSTRAINT_SCRIPT = #CREATE_CONSTRAINT_SCRIPT +
'ALTER TABLE '+FK_Table+'
ADD CONSTRAINT '+FK_Name+'
FOREIGN KEY ('+FK_Column+') REFERENCES '+PK_Table+'('+PK_Column+');
'
FROM (
SELECT RC.CONSTRAINT_NAME FK_Name
, KF.TABLE_SCHEMA FK_Schema
, KF.TABLE_NAME FK_Table
, KF.COLUMN_NAME FK_Column
, RC.UNIQUE_CONSTRAINT_NAME PK_Name
, KP.TABLE_SCHEMA PK_Schema
, KP.TABLE_NAME PK_Table
, KP.COLUMN_NAME PK_Column
, RC.MATCH_OPTION MatchOption
, RC.UPDATE_RULE UpdateRule
, RC.DELETE_RULE DeleteRule
FROM INFORMATION_SCHEMA.REFERENTIAL_CONSTRAINTS RC
JOIN INFORMATION_SCHEMA.KEY_COLUMN_USAGE KF ON RC.CONSTRAINT_NAME = KF.CONSTRAINT_NAME
JOIN INFORMATION_SCHEMA.KEY_COLUMN_USAGE KP ON RC.UNIQUE_CONSTRAINT_NAME = KP.CONSTRAINT_NAME
WHERE KP.TABLE_NAME='TABLE_NAME_TRUNCATE'
) TBL
-- DROP CONSTRAINTS
EXEC( #DROP_CONSTRAINT_SCRIPT);
-------
-- TRUNCATE TABLE SCRIPT NEEDS TO BE PUT BELOW
-------
TRUNCATE TABLE TABLE_NAME_TRUNCATE
-- RECREATE CONSTRAINTS
EXEC( #CREATE_CONSTRAINT_SCRIPT);
SET FOREIGN_KEY_CHECKS=0;
TRUNCATE table1;
TRUNCATE table2;
SET FOREIGN_KEY_CHECKS=1;
reference - truncate foreign key constrained table
Working for me in MYSQL
You could try DELETE FROM <your table >;.
The server will show you the name of the restriction and the table, and deleting that table you can delete what you need.
I have just found that you can use TRUNCATE table on a parent table with foreign key constraints on a child as long as you DISABLE the constraints on the child table first.
E.g.
Foreign key CONSTRAINT child_par_ref on child table, references PARENT_TABLE
ALTER TABLE CHILD_TABLE DISABLE CONSTRAINT child_par_ref;
TRUNCATE TABLE CHILD_TABLE;
TRUNCATE TABLE PARENT_TABLE;
ALTER TABLE CHILD_TABLE ENABLE CONSTRAINT child_par_ref;
The easiest way:
1 - Enter in phpmyadmin
2 - Click on table name in left column
3 - Click in Operation (top menu)
4 - Click "Empty the table (TRUNCATE)
5 - Disable box "Enable foreign key checks"
6 - Done!
Link to image tutorial
Tutorial: http://www.imageno.com/wz6gv1wuqajrpic.html
(sorry, I don't have enough reputation to upload images here :P)