如何使用TSQL截断数据库中的所有表?
我有一个数据库的testing环境,我想在testing周期开始时用新数据重新加载。 我对重build整个数据库不感兴趣 – 只是简单地“重新设置”数据。
使用TSQL从所有表中删除所有数据的最好方法是什么? 有系统存储过程,视图等可以使用? 我不想为每个表手动创build和维护截断表语句,我宁愿它是dynamic的。
对于SQL 2005,
EXEC sp_MSForEachTable 'TRUNCATE TABLE ?'
夫妇更多的链接2000年和2005/2008年 ..
当处理从具有外键关系的表中删除数据时(基本上是任何devise正确的数据库),我们可以禁用所有约束,删除所有数据,然后重新启用约束
-- 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"
更多关于在这里禁用约束和触发器
如果某些表格有标识列,我们可能想要重新标记它们
EXEC sp_MSForEachTable "DBCC CHECKIDENT ( '?', RESEED, 0)"
请注意,RESEED的行为在全新表格和先前从BOL插入过一些数据的行为之间有所不同:
DBCC CHECKIDENT('table_name',RESEED,newReseedValue)
当前标识值设置为newReseedValue。 如果自创build之后没有行插入到表中,则在执行DBCC CHECKIDENT之后插入的第一行将使用newReseedValue作为标识。 否则,插入的下一行将使用newReseedValue + 1.如果newReseedValue的值小于标识列中的最大值,那么将在随后引用表时生成错误消息2627。
感谢罗伯特指出禁用约束不允许使用截断的事实,约束将不得不被删除,然后重新创build
这是国王爸爸的数据库擦拭脚本。 它将清除所有的表格并正确地重新input:
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'
享受,但要小心!
做这个最简单的方法是
- 打开SQL Management Studio
- 导航到您的数据库
- 右键单击并select任务 – >生成脚本(图1)
- 在“select对象”屏幕上,select“select特定对象”选项并检查“表”(图2)
- 在下一个屏幕上,select“高级”,然后将“脚本删除和创build”选项更改为“脚本删除和创build”(图3)
- select将脚本保存到新的编辑器窗口或文件,并根据需要运行。
这将为您提供一个脚本,可以删除并重新创build所有表,而无需担心debugging或是否包含所有内容。 虽然这不仅仅是一个截断,结果是相同的。 请记住,您的自动递增主键将从0开始,而不是被截断的表,它们会记住分配的最后一个值。 如果您无法访问PreProd或生产环境中的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的替代选项是在创build空模式后立即创build数据库的快照。 在这一点上,你可以保持恢复数据库的快照。
不要这样做! 真的,不是一个好主意。
如果您知道要截断哪些表,请创build一个截断它们的存储过程。 您可以修复该命令以避免外键问题。
如果你真的想截断它们(例如你可以用BCP加载它们),那么你就可以快速地删除数据库,并从头开始创build一个新的数据库,这将有更多的好处,你知道你在哪里。
创build一个空的“模板”数据库,进行完整备份。 当你需要刷新时,只需使用WITH REPLACE恢复即可。 快速,简单,防弹。 如果在这里或那里有一些表需要一些基础数据(例如configuration信息,或者只是使您的应用程序运行的基本信息),它也可以处理。
如果你想保留数据在一个特定的表(即静态查找表),同时删除/截断在同一个数据库中的其他表中的数据,那么你需要一个循环与例外。 当我偶然发现这个问题的时候,这就是我正在寻找的东西。
sp_MSForEachTable似乎对我来说是越位(即与IF语句不一致的行为),这可能是为什么它没有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
这是做到这一点的一种方法…有可能有更好/更有效的其他10个,但这听起来像很less做,所以这里…
从sysobjects获得表的列表,然后用游标循环遍历这些表,为每个迭代调用sp_execsql('truncate table'+ @table_name)。
脚本化数据库要容易得多(甚至可能更快),然后从脚本中删除并创build它。
截断所有表格中最难的部分是删除并重新添加外键约束。
以下查询为@myTempTable中与每个表名相关的每个约束创builddrop&create语句。 如果您想为所有表生成这些表,您可以简单地使用信息模式来收集这些表名。
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)
然后,我只是复制语句运行 – 但有一点开发努力,你可以使用游标dynamic运行它们。
我不明白为什么清理数据比删除和重新创build每个表的脚本更好。
或者保留你的空白数据库的备份,并将其恢复到原来的状态
在截断表之前,你必须删除所有的外键。 使用此脚本生成最终脚本以删除并重新创build数据库中的所有外键。 请将@actionvariables设置为“CREATE”或“DROP”。
运行注释掉的部分一次,用你想截断的表填充_TruncateList表,然后运行脚本的其余部分。 如果你经常这样做的话,需要清理_ScriptLog表。
你可以修改这个,如果你想要做所有的表,只要把SELECT name INTO #TruncateList FROM sys.tables。 但是,你通常不想全部做。
此外,这将影响数据库中的所有外键,如果对应用程序过于直接,也可以对其进行修改。 这不是我的目的。
/* 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
从INFORMATION_SCHEMA.TABLES中select“删除”+ TABLE_NAME,其中TABLE_TYPE ='BASE TABLE'
结果来了。
复制并粘贴到查询窗口并运行命令