如何从 SQLServer 数据库中的所有表中删除所有行?

如何从 SQLServer 数据库中的所有表中删除所有行?

225083 次浏览

请注意,如果您有任何参照完整性设置,TRUNCATE 将无法工作。

在这种情况下,这种做法将会奏效:

EXEC sp_MSForEachTable 'DISABLE TRIGGER ALL ON ?'
GO
EXEC sp_MSForEachTable 'ALTER TABLE ? NOCHECK CONSTRAINT ALL'
GO
EXEC sp_MSForEachTable 'SET QUOTED_IDENTIFIER ON; DELETE FROM ?'
GO
EXEC sp_MSForEachTable 'ALTER TABLE ? WITH CHECK CHECK CONSTRAINT ALL'
GO
EXEC sp_MSForEachTable 'ENABLE TRIGGER ALL ON ?'
GO

编辑: 需要说明的是,报表中的 ??。它被 sp_MSForEachTable过程替换为表名。

您可以使用 Rubens 建议的方法从所有表中删除所有行,也可以直接删除并重新创建所有表。无论如何,拥有完整的 db 创建脚本总是一个好主意,这可能是最简单/最快速的方法。

如果要删除整个表,则必须遵循下一条 SQL 指令

Delete  FROM TABLE Where PRIMARY_KEY_ is Not NULL;

我不得不删除所有的行,然后用下一个脚本:

DECLARE @Nombre NVARCHAR(MAX);
DECLARE curso CURSOR FAST_FORWARD
FOR
Select Object_name(object_id) AS Nombre from sys.objects where type = 'U'


OPEN curso
FETCH NEXT FROM curso INTO @Nombre


WHILE (@@FETCH_STATUS <> -1)
BEGIN
IF (@@FETCH_STATUS <> -2)
BEGIN
DECLARE @statement NVARCHAR(200);
SET @statement = 'DELETE FROM ' + @Nombre;
print @statement
execute sp_executesql @statement;
END
FETCH NEXT FROM curso INTO @Nombre
END
CLOSE curso
DEALLOCATE curso

希望这个能帮上忙!

Set nocount on


Exec sp_MSforeachtable 'Alter Table ? NoCheck Constraint All'


Exec sp_MSforeachtable
'
If ObjectProperty(Object_ID(''?''), ''TableHasForeignRef'')=1
Begin
-- Just to know what all table used delete syntax.
Print ''Delete from '' + ''?''
Delete From ?
End
Else
Begin
-- Just to know what all table used Truncate syntax.
Print ''Truncate Table '' + ''?''
Truncate Table ?
End
'


Exec sp_MSforeachtable 'Alter Table ? Check Constraint All'

在我最近的项目中,我的任务是使用 sql 语句清理整个数据库,并且每个表都有许多约束,比如主键和外键。数据库中有1000多个表,因此不可能对每个表写一个删除查询。

通过使用一个名为 Sp _ MSForEachTable的存储过程,我们可以轻松地对单个数据库中的每个表处理一些代码。这意味着它用于处理数据库中每个表的单个 T-SQL 命令或不同的 T-SQL 命令。

因此,按照以下步骤截断 SQLServer 数据库中的所有表:

步骤1-使用下面的 sql 查询禁用数据库上的所有约束:

EXEC sys.sp_msforeachtable 'ALTER TABLE ? NOCHECK CONSTRAINT ALL'

步骤2-使用下面的 sql 命令对数据库的每个表执行删除或截断操作:

EXEC sys.sp_msforeachtable 'DELETE FROM ?'

步骤3-使用下面的 sql 语句启用数据库上的所有约束:

EXEC sys.sp_MSForEachTable 'ALTER TABLE ? CHECK CONSTRAINT ALL'

这里有一个解决方案:

  1. 放弃约束(感谢 这个后)
  2. 对特定数据库遍历 INFORMATION_SCHEMA.TABLES
  3. 基于某些搜索条件的 SELECTS
  4. 删除这些表中的所有数据
  5. 重新添加约束
  6. 允许忽略某些表,如 sysdiagrams__RefactorLog

我最初尝试了 EXECUTE sp_MSforeachtable 'TRUNCATE TABLE ?',但它删除了我的图表。

USE <DB name>;
GO


-- Disable all constraints in the database
EXEC sp_MSforeachtable "ALTER TABLE ? NOCHECK CONSTRAINT all"


declare @catalog nvarchar(250);
declare @schema nvarchar(250);
declare @tbl nvarchar(250);
DECLARE i CURSOR LOCAL FAST_FORWARD FOR select
TABLE_CATALOG,
TABLE_SCHEMA,
TABLE_NAME
from INFORMATION_SCHEMA.TABLES
where
TABLE_TYPE = 'BASE TABLE'
AND TABLE_NAME != 'sysdiagrams'
AND TABLE_NAME != '__RefactorLog'


OPEN i;
FETCH NEXT FROM i INTO @catalog, @schema, @tbl;
WHILE @@FETCH_STATUS = 0
BEGIN
DECLARE @sql NVARCHAR(MAX) = N'DELETE FROM [' + @catalog + '].[' + @schema + '].[' + @tbl + '];'
/* Make sure these are the commands you want to execute before executing */
PRINT 'Executing statement: ' + @sql
-- EXECUTE sp_executesql @sql
FETCH NEXT FROM i INTO @catalog, @schema, @tbl;
END
CLOSE i;
DEALLOCATE i;


-- Re-enable all constraints again
EXEC sp_MSforeachtable "ALTER TABLE ? WITH CHECK CHECK CONSTRAINT all"

对于某些需求,我们可能不得不跳过某些表。我编写了下面的脚本来添加一些额外的条件来过滤表列表。下面的脚本还将显示预删除计数和后删除计数。

        IF OBJECT_ID('TEMPDB..#TEMPRECORDCOUNT') IS NOT NULL
DROP TABLE #TEMPRECORDCOUNT


CREATE TABLE #TEMPRECORDCOUNT
(    TABLENAME NVARCHAR(128)
,PREDELETECOUNT BIGINT
,POSTDELETECOUNT BIGINT
)


INSERT INTO #TEMPRECORDCOUNT (TABLENAME, PREDELETECOUNT, POSTDELETECOUNT)


SELECT   O.name TableName
,DDPS.ROW_COUNT PREDELETECOUNT
,NULL  FROM sys.objects O


INNER JOIN (


SELECT OBJECT_ID, SUM(row_count) ROW_COUNT
FROM SYS.DM_DB_PARTITION_STATS
GROUP BY OBJECT_ID
) DDPS ON DDPS.OBJECT_ID = O.OBJECT_ID
WHERE O.type = 'U' AND O.name NOT LIKE 'OC%' AND O.schema_id = 1


DECLARE @TableName NVARCHAR(MAX);
DECLARE TableDeleteCursor CURSOR FAST_FORWARD
FOR
SELECT TableName from #TEMPRECORDCOUNT


OPEN TableDeleteCursor
FETCH NEXT FROM TableDeleteCursor INTO @TableName


WHILE (@@FETCH_STATUS <> -1)
BEGIN
IF (@@FETCH_STATUS <> -2)
BEGIN
DECLARE @STATEMENT NVARCHAR(MAX);
SET @STATEMENT = ' DISABLE TRIGGER ALL ON ' + @TableName +
'; ALTER TABLE ' + @TableName + ' NOCHECK CONSTRAINT ALL' +
'; DELETE FROM ' + @TableName +
'; ALTER TABLE ' + @TableName + ' CHECK CONSTRAINT ALL' +
'; ENABLE TRIGGER ALL ON ' + @TableName;
PRINT @STATEMENT
EXECUTE SP_EXECUTESQL @STATEMENT;
END
FETCH NEXT FROM TableDeleteCursor INTO @TableName
END
CLOSE TableDeleteCursor
DEALLOCATE TableDeleteCursor


UPDATE T
SET T.POSTDELETECOUNT = I.ROW_COUNT
FROM #TEMPRECORDCOUNT T
INNER JOIN (
SELECT O.name TableName, DDPS.ROW_COUNT ROW_COUNT
FROM sys.objects O
INNER JOIN (


SELECT OBJECT_ID, SUM(row_count) ROW_COUNT
FROM SYS.DM_DB_PARTITION_STATS
GROUP BY OBJECT_ID
) DDPS ON DDPS.OBJECT_ID = O.OBJECT_ID
WHERE O.type = 'U' AND O.name NOT LIKE 'OC%' AND O.schema_id = 1


) I ON I.TableName COLLATE DATABASE_DEFAULT = T.TABLENAME


SELECT * FROM #TEMPRECORDCOUNT
ORDER BY TABLENAME ASC

在我的例子中,我需要设置 QUOTED _ IDENTIFIER,这导致对 Mark Rendle 上面的答案稍作修改:

EXEC sp_MSforeachtable 'DISABLE TRIGGER ALL ON ?'
GO
EXEC sp_MSforeachtable 'ALTER TABLE ? NOCHECK CONSTRAINT ALL'
GO
EXEC sp_MSforeachtable 'SET QUOTED_IDENTIFIER ON; DELETE FROM ?'
GO
EXEC sp_MSforeachtable 'ALTER TABLE ? CHECK CONSTRAINT ALL'
GO
EXEC sp_MSforeachtable 'ENABLE TRIGGER ALL ON ?'
GO

这个答案也建立在扎克 · 史密斯 重置标识列的答案之上:

  1. 禁用所有约束
  2. 迭代所有表(选择排除的表除外)
  3. 删除表中的所有行
  4. 如果存在标识列,则重置标识列
  5. 重新启用所有约束

这里有一个问题:

-- Disable all constraints in the database
EXEC sp_msforeachtable "ALTER TABLE ? NOCHECK CONSTRAINT all"


declare @catalog nvarchar(250);
declare @schema nvarchar(250);
declare @tbl nvarchar(250);
DECLARE i CURSOR LOCAL FAST_FORWARD FOR select
TABLE_CATALOG,
TABLE_SCHEMA,
TABLE_NAME
from INFORMATION_SCHEMA.TABLES
where
TABLE_TYPE = 'BASE TABLE'
AND TABLE_NAME != 'sysdiagrams'
AND TABLE_NAME != '__RefactorLog'
-- Optional
-- AND (TABLE_SCHEMA = 'dbo')


OPEN i;
FETCH NEXT FROM i INTO @catalog, @schema, @tbl;
WHILE @@FETCH_STATUS = 0
BEGIN
DECLARE @sql NVARCHAR(MAX) = N'DELETE FROM [' + @catalog + '].[' + @schema + '].[' + @tbl + '];'
/* Make sure these are the commands you want to execute before executing */
PRINT 'Executing statement: ' + @sql
--EXECUTE sp_executesql @sql


-- Reset identity counter if one exists
IF ((SELECT OBJECTPROPERTY( OBJECT_ID(@catalog + '.' + @schema + '.' + @tbl), 'TableHasIdentity')) = 1)
BEGIN
SET @sql = N'DBCC CHECKIDENT ([' + @catalog + '.' + @schema + '.' + @tbl + '], RESEED, 0)'
PRINT 'Executing statement: ' + @sql
--EXECUTE sp_executesql @sql
END


FETCH NEXT FROM i INTO @catalog, @schema, @tbl;
END
CLOSE i;
DEALLOCATE i;


-- Re-enable all constraints again
EXEC sp_msforeachtable "ALTER TABLE ? WITH CHECK CHECK CONSTRAINT all"
--Load tables to delete from
SELECT
DISTINCT
' Delete top 1000000 from <DBName>.<schema>.' + c.TABLE_NAME + ' WHERE <Filter Clause Here>' AS query,c.TABLE_NAME AS TableName, IsDeleted=0, '<InsertSomeDescriptorHere>' AS [Source]--,t.TABLE_TYPE, c.*
INTO dbo.AllTablesToDeleteFrom
FROM INFORMATION_SCHEMA.TABLES AS t
INNER JOIN information_schema.columns c ON c.TABLE_NAME = t.TABLE_NAME
WHERE c.COLUMN_NAME = '<column name>'
AND c.TABLE_SCHEMA = 'dbo'
AND c.TABLE_CATALOG = '<DB Name here>'
AND t.TABLE_TYPE='Base table'
--AND t.TABLE_NAME LIKE '<put filter here>'


DECLARE @TableSelect NVARCHAR(1000)= '';
DECLARE @Table NVARCHAR(1000)= '';
DECLARE @IsDeleted INT= 0;
DECLARE @NumRows INT = 1000000;
DECLARE @Source NVARCHAR(50)='';




WHILE ( @IsDeleted = 0 )
BEGIN
--This grabs one table at a time to be deleted from. @TableSelect has the sql to execute. it is important to order by IsDeleted ASC
--because it will pull tables to delete from by those that have a 0=IsDeleted first. Once the loop grabs a table with IsDeleted=1 then this will pop out of loop


SELECT TOP 1
@TableSelect = query,
@IsDeleted = IsDeleted,
@Table = TableName,
@Source=[a].[Source]
FROM    dbo.AllTablesToDeleteFrom a
WHERE a.[Source]='SomeDescriptorHere'--use only if needed
ORDER BY a.IsDeleted ASC;--this is required because only those records returned with IsDeleted=0 will run through loop


--SELECT  @Table; can add this in to  monitor what table is being deleted from


WHILE ( @NumRows = 1000000 )--only delete a million rows at a time?


BEGIN
EXEC sp_executesql @TableSelect;
SET @NumRows = @@ROWCOUNT;
--IF @NumRows = 1000000 --can do something here if needed
--One wants this loop to continue as long as a million rows is deleted. Once < 1 million rows is deleted it pops out of loop
--and grabs next table to delete
--    BEGIN
--SELECT  @NumRows;--can add this in to see current number of deleted records for table
INSERT  INTO dbo.DeleteFromAllTables
( tableName,
query,
cnt,
[Source]
)
SELECT  @Table,
@TableSelect,
@NumRows,
@Source;
--   END;
END;






SET @NumRows = 1000000;


UPDATE  a
SET     a.IsDeleted = 1
FROM    dbo.AllTablesToDeleteFrom a
WHERE   a.TableName = @Table;
--flag this as deleted so you can move on to the next table to delete from


END;

如果只有约束,只需将这几行粘贴到查询中并运行它

EXEC sys.sp_msforeachtable 'ALTER TABLE ? NOCHECK CONSTRAINT ALL'
EXEC sys.sp_msforeachtable 'DELETE FROM ?'
EXEC sys.sp_MSForEachTable 'ALTER TABLE ? CHECK CONSTRAINT ALL'