【问题标题】:How to delete all rows from all tables in a SQL Server database?如何从 SQL Server 数据库中的所有表中删除所有行?
【发布时间】:2009-12-14 09:19:27
【问题描述】:

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

【问题讨论】:

标签: sql-server-2005


【解决方案1】:

请注意,如果您设置了任何参照完整性,则 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 过程替换为表名。

【讨论】:

  • 实际上,这仅适用于 DDL 触发器。在这种情况下: EXECP sp_MSForEachTable 'DISABLE TRIGGER ALL ON ?'
  • 在 SQL Azure 中不可用 :(
  • 知道了 - 如果备份文件已经存在,那么看起来 SSMS 会附加到它而不是替换它(我没有意识到这一点)。所以我删除了文件,现在“空”数据库备份文件只有 3.7 MB
  • 如果我想选择数据库怎么办,比如:USE [MyDataBase]?如果以某种方式进行调整,上述想法是否可行?...因为我不想删除 SQL 服务器保留的所有数据库。
  • 这里是为 SQL Azure gist.github.com/metaskills/893599创建 sp_MSForEachTable 过程的链接
【解决方案2】:

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

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

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

步骤 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'

【讨论】:

  • 您可以简单地执行步骤 2 多次,以便第一次删除不依赖的表,第二次删除第一次失败的表,第三次删除第二次失败的表,等等跨度>
  • 关于如何在sql server azure 上执行此操作的任何想法?
  • 这种方法也适用于 Azure,因为它只使用普通 SQL:sqlrelease.com/delete-all-rows-from-all-tables
【解决方案3】:

我不得不删除所有行并使用下一个脚本完成:

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

希望这会有所帮助!

【讨论】:

  • 感谢这个,因为我需要调整选择以消除一些表格。这很有效。
【解决方案4】:

就我而言,我需要设置 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

【讨论】:

  • 为我工作 - 在我收到此错误之前:DELETE failed because the following SET options have incorrect settings: 'QUOTED_IDENTIFIER'. Verify that SET options are correct for use with indexed views and/or indexes on computed columns and/or filtered indexes and/or query notifications and/or XML data type methods and/or spatial index operations.
【解决方案5】:

这是一个解决方案:

  1. 放弃限制(感谢this 帖子)
  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"

【讨论】:

  • 这很好,但它没有考虑到非 dbo 模式。
  • 我从未使用过非 dbo 模式,所以我不会明白这一点。但为什么它不起作用?我没有在任何地方指定架构,所以它默认为仅 dbo 吗?
  • 如果您有一个表,例如名为 test.Table1,其中“test”是架构,如果尝试执行“DELETE FROM Table1”,您的删除操作将失败。它需要从 test.Table1 中删除。
  • @influent - 现在它考虑了非 dbo 模式
  • 确实是@FluidMechanicsPotentialFlows - EXECUTE sp_executesql @sql 语句已被注释掉。这是以防万一有人将此 SQL 复制/粘贴到 SSMS 中而不先阅读它
【解决方案6】:
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'

【讨论】:

    【解决方案7】:

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

    【讨论】:

    • 似乎 OP 关心参照完整性和触发器;这种情况下,你得到了最好的解决方案。我放弃了我的答案 =)
    【解决方案8】:

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

            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
    

    【讨论】:

      【解决方案9】:

      此答案通过重置身份列建立在 Zach Smith 的答案之上:

      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"
      

      【讨论】:

      • 由于某种原因,这通常会失败,因为它会引发 FK 约束错误。
      【解决方案10】:
      --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; 
      

      【讨论】:

        【解决方案11】:

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

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

        【讨论】:

          【解决方案12】:

          如果要删除整张表,必须按照下一条SQL指令进行

          Delete  FROM TABLE Where PRIMARY_KEY_ is Not NULL;
          

          【讨论】:

            猜你喜欢
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 2011-04-10
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            相关资源
            最近更新 更多