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
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)
/*
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
17 回答
对于SQL 2005,
为2000和2005/2008结合更多链接..
当处理从具有外键关系的表中删除数据时 - 基本上是任何设计合理的数据库的情况 - 我们可以禁用所有约束,删除所有数据然后重新启用约束
有关禁用约束和触发器的更多信息here
如果某些表具有标识列,我们可能需要重新设置它们
请注意,RESEED的行为在全新表和之前从BOL插入了一些数据的表之间有所不同:
感谢Robert指出禁用约束不允许使用truncate的事实,必须删除约束,然后重新创建
这是数据库擦除脚本的国王 . 它将清除所有表并正确重新设置它们:
享受,但要小心!
最简单的方法是
打开SQL Management Studio
导航到您的数据库
右键单击并选择任务 - >生成脚本(图1)
在"choose Objects"屏幕上,选择"select specific objects"选项并检查"tables"(图2)
在下一个屏幕上,选择"advanced",然后将"Script DROP and CREATE"选项更改为"Script DROP and CREATE"(图3)
选择将脚本保存到新的编辑器窗口或文件,并根据需要运行 .
这将为您提供一个脚本,可以删除并重新创建所有表,而无需担心调试或是否包含所有内容 . 虽然这不仅仅是截断,但结果是相同的 . 请记住,自动递增主键将从0开始,而截断表将记住最后分配的值 . 如果您无法访问PreProd或Production环境中的Management studio,也可以从代码执行此操作 .
1 .
2 .
3 .
截断所有表只有在表之间没有任何外键关系时才会起作用,因为SQL Server不允许您使用外键截断表 .
另一种方法是使用外键确定表并从中删除,然后可以在没有外键的情况下截断表 .
有关详细信息,请参阅http://www.sqlteam.com/forums/topic.asp?TOPIC_ID=65341和http://www.sqlteam.com/forums/topic.asp?TOPIC_ID=72957 .
我喜欢与MSSQL Server Deveploper或Enterprise一起使用的另一种选择是在创建空模式后立即创建数据库的快照 . 此时,您可以继续将数据库还原到快照 .
不要这样做!真的,不是一个好主意 .
如果您知道要截断哪些表,请创建一个截断它们的存储过程 . 您可以修复订单以避免外键问题 .
如果你真的想要截断它们(例如你可以BCP加载它们),那么你可以快速删除数据库并从头开始创建一个新的数据库,这将带来额外的好处,你可以确切地知道它在哪里 .
如果要在同一数据库中的其他表中删除/截断数据时将数据保存在特定表(即静态查找表)中,则需要一个包含异常的循环 . 当我偶然发现这个问题时,这正是我所寻找的 .
sp_MSForEachTable对我来说似乎有些错误(即与IF语句的行为不一致),这可能就是为什么它没有记录由MS .
创建一个空的“模板”数据库,进行完整备份 . 需要刷新时,只需使用WITH REPLACE进行恢复 . 快速,简单,防弹 . 如果这里或那里的几个表需要一些基本数据(例如配置信息,或只是让你的应用程序运行的基本信息),它也会处理它 .
截断所有表最难的部分是删除和重新定义外键约束 .
以下查询为@myTempTable中与每个表名相关的每个约束创建drop和create语句 . 如果您想为所有表生成这些表,您可以简单地使用信息模式来收集这些表名 .
然后我只是复制出要运行的语句 - 但是通过一些开发工作,你可以使用游标动态运行它们 .
编写数据库脚本要容易得多(甚至可能更快),然后从脚本中删除并创建它 .
这是一种方法...有可能有10个更好/更有效,但听起来这种情况很少发生,所以这里......
从
sysobjects
获取tables
的列表,然后循环使用游标,为每个iteration
调用sp_execsql('truncate table ' + @table_name)
.我不明白为什么清除数据会比删除和重新创建每个表的脚本更好 .
那或者保留空数据库的备份并将其恢复到旧数据库
在截断表之前,您必须删除所有外键 . 使用此script生成最终脚本以删除并重新创建数据库中的所有外键 . 请将@action变量设置为'CREATE'或'DROP' .
运行注释掉的部分一次,使用要截断的表填充_TruncateList表,然后运行脚本的其余部分 . 如果你这么做的话,需要随时清理_ScriptLog表 .
如果要执行所有表,只需将SELECT名称INTO #TruncateList FROM sys.tables放入,就可以修改它 . 但是,您通常不希望全部执行这些操作 .
此外,这将影响数据库中的所有外键,如果它对您的应用程序来说太过钝,您也可以修改它 . 这不适合我的目的 .
这有点晚了,但它可能对某人有所帮助 . 我有时会创建一个过程,使用T-SQL执行以下操作:
将所有约束存储在临时表中
删除所有约束
截断除了某些表之外的所有表,这些表不需要截断
重新创建所有约束 .
我在我的博客上列出了它here
从INFORMATION_SCHEMA.TABLES中选择'从'TABLE_NAME删除TABLE_TYPE ='BASE TABLE'
结果来了 .
复制并粘贴查询窗口并运行该命令