【问题标题】:SQL TRUNCATE DATABASE ? How to TRUNCATE ALL TABLESSQL 截断数据库?如何截断所有表格
【发布时间】:2011-08-27 02:28:24
【问题描述】:

我使用 SQL Server 2008 R2。

是否有一个 SQL 命令可以清空数据库,而不必截断我的所有 20 个表?

我只想删除数据而不是结构。

【问题讨论】:

  • 虽然是一个有效的问题,但显然任何答案都会涉及到一个危险的实体(例如存储过程)——上帝帮助那些意外运行它的人!

标签: database sql-server-2008 truncate


【解决方案1】:

转到数据库结构 -> 全选 -> 空

它将对所有表执行 TRUNCATE,只需点击 OK。

【讨论】:

    【解决方案2】:

    因为我的目的是获得一个空版本的测试数据库,以便在一切都经过微调后从外部先前的当前活动源(Access 数据库)导入数据。我发现使用带有 Verify_CloneDB 选项的 DBCC CloneDatabase 非常合适。

    【讨论】:

      【解决方案3】:
      ---- Remove Constraint ----
      EXEC sp_MSForEachTable "ALTER TABLE ? NOCHECK CONSTRAINT all"
      
      ---- Delete Data ----
      EXEC sp_MSForEachTable "DELETE FROM ?"
      
      ---- Add Constraint ----
      EXEC sp_MSForEachTable "ALTER TABLE ? WITH CHECK CHECK CONSTRAINT all"
      
      ---- Reset Identity value ----
      EXEC sp_MSForEachTable "DBCC CHECKIDENT ( '?', RESEED, 0)"
      

      【讨论】:

        【解决方案4】:

        如果您只想截断特定架构中的所有表,也可以使用此存储过程:

        -- =============================================
        -- Author:      Ben de Ridder
        -- Create date: 20160513
        -- Description: Truncate all tables in schema
        -- =============================================
        CREATE PROCEDURE TruncateAllTablesInSchema
            @schema nvarchar(50)
        AS
        BEGIN
            -- SET NOCOUNT ON added to prevent extra result sets from
            -- interfering with SELECT statements.
            SET NOCOUNT ON;
        
            DECLARE @table nVARCHAR(255)
        
            DECLARE db_cursor CURSOR FOR 
                select t.name
                  from sys.tables t inner join
                       sys.schemas s on 
                            t.schema_id=s.schema_id
                 where s.name=@schema
                 order by 1
        
            OPEN db_cursor   
        
            FETCH NEXT FROM db_cursor INTO @table   
        
            WHILE @@FETCH_STATUS = 0   
            BEGIN   
                   declare @sql nvarchar(1000)
        
                   set @sql = 'truncate table [' + @schema + '].[' + @table + ']'
        
                   exec sp_sqlexec @sql
        
                   FETCH NEXT FROM db_cursor INTO @table   
            END   
        
            CLOSE db_cursor   
            DEALLOCATE db_cursor 
        
        END
        GO
        

        【讨论】:

          【解决方案5】:

          没有废话脚本:

          EXEC sp_MSForEachTable 'ALTER TABLE ? NOCHECK CONSTRAINT ALL'
          EXEC sp_MSForEachTable 'DELETE FROM ?'
          EXEC sp_MSForEachTable 'ALTER TABLE ? CHECK CONSTRAINT ALL'
          EXEC sp_MSforeachtable 'DBCC CHECKIDENT ( ''?'', RESEED, 0)'
          GO
          

          如果表中有外键,截断仍然不起作用。 此脚本还将重置所有标识列。

          【讨论】:

            【解决方案6】:

            执行这个

            EXEC sp_MSforeachtable 'PRINT ''ALTER TABLE ? NOCHECK CONSTRAINT ALL'''
            EXEC sp_MSforeachtable 'print ''DELETE FROM ?'''
            EXEC sp_MSforeachtable 'print ''ALTER TABLE ? WITH CHECK CHECK CONSTRAINT all'''
            

            复制打印结果并将其粘贴到查询字段并执行后。它将截断所有表。

            【讨论】:

              【解决方案7】:

              从 Boycs Answer 和 mtmurdock 的后续回答中得出一个观点,我在所有开发或暂存数据库中都有以下存储过程。如果我需要添加语句来重新植入某些列的数据,我已经添加了一些开关以满足我自己的要求。

              注意:我会将此添加为对 Boycs 出色答案的评论,但我还没有足够的声誉来做到这一点。所以请接受我的道歉,将其添加为一个全新的答案。)

              ALTER PROCEDURE up_ResetEntireDatabase
              @IncludeIdentReseed BIT,
              @IncludeDataReseed BIT
              AS
              
              EXEC sp_MSForEachTable 'ALTER TABLE ? NOCHECK CONSTRAINT ALL'
              EXEC sp_MSForEachTable 'DELETE FROM ?'
              
              IF @IncludeIdentReseed = 1
              BEGIN
                  EXEC sp_MSForEachTable 'DBCC CHECKIDENT (''?'' , RESEED, 1)'
              END
              
              EXEC sp_MSForEachTable 'ALTER TABLE ? CHECK CONSTRAINT ALL'
              
              IF @IncludeDataReseed = 1
              BEGIN
                  -- Populate Core Data Table Here
              END
              GO
              

              然后一旦准备好执行就很简单了:

              EXEC up_ResetEntireDatabase 1, 1
              

              【讨论】:

                【解决方案8】:

                提供的大多数解决方案要么不使用与 DELETE 不同的 TRUNCATE,要么不处理外键约束问题。 Chaitanya 提供的解决方案很接近,但它回退到使用 DELETE,并且它在存储过程中执行它,这似乎不适合您在数据库中对所有数据进行核对的情况。

                所以,下面是我的变体,它确实使用了 TRUNCATE 并解决了外键约束问题。

                    /* TRUNCATE ALL TABLES IN A DATABASE */
                
                DECLARE @dropAndCreateConstraintsTable TABLE
                        (
                         DropStmt VARCHAR(MAX)
                        ,CreateStmt VARCHAR(MAX)
                        )
                /* Gather information to drop and then recreate the current foreign key constraints  */
                INSERT  @dropAndCreateConstraintsTable
                        SELECT  DropStmt = 'ALTER TABLE [' + ForeignKeys.ForeignTableSchema
                                + '].[' + ForeignKeys.ForeignTableName + '] DROP CONSTRAINT ['
                                + ForeignKeys.ForeignKeyName + ']; '
                               ,CreateStmt = 'ALTER TABLE [' + ForeignKeys.ForeignTableSchema
                                + '].[' + ForeignKeys.ForeignTableName
                                + '] WITH CHECK ADD CONSTRAINT [' + ForeignKeys.ForeignKeyName
                                + '] FOREIGN KEY([' + ForeignKeys.ForeignTableColumn
                                + ']) REFERENCES [' + SCHEMA_NAME(sys.objects.schema_id)
                                + '].[' + sys.objects.[name] + ']([' + sys.columns.[name]
                                + ']); '
                        FROM    sys.objects
                        INNER JOIN sys.columns
                                ON ( sys.columns.[object_id] = sys.objects.[object_id] )
                        INNER JOIN ( SELECT sys.foreign_keys.[name] AS ForeignKeyName
                                           ,SCHEMA_NAME(sys.objects.schema_id) AS ForeignTableSchema
                                           ,sys.objects.[name] AS ForeignTableName
                                           ,sys.columns.[name] AS ForeignTableColumn
                                           ,sys.foreign_keys.referenced_object_id AS referenced_object_id
                                           ,sys.foreign_key_columns.referenced_column_id AS referenced_column_id
                                     FROM   sys.foreign_keys
                                     INNER JOIN sys.foreign_key_columns
                                            ON ( sys.foreign_key_columns.constraint_object_id = sys.foreign_keys.[object_id] )
                                     INNER JOIN sys.objects
                                            ON ( sys.objects.[object_id] = sys.foreign_keys.parent_object_id )
                                     INNER JOIN sys.columns
                                            ON ( sys.columns.[object_id] = sys.objects.[object_id] )
                                               AND ( sys.columns.column_id = sys.foreign_key_columns.parent_column_id )
                                   ) ForeignKeys
                                ON ( ForeignKeys.referenced_object_id = sys.objects.[object_id] )
                                   AND ( ForeignKeys.referenced_column_id = sys.columns.column_id )
                        WHERE   ( sys.objects.[type] = 'U' )
                                AND ( sys.objects.[name] NOT IN ( 'sysdiagrams' ) )
                
                /* SELECT * FROM @dropAndCreateConstraintsTable AS DACCT */
                
                DECLARE @DropStatement NVARCHAR(MAX)
                DECLARE @RecreateStatement NVARCHAR(MAX)
                
                /* Drop Constraints */
                DECLARE C1 CURSOR READ_ONLY
                FOR
                        SELECT  DropStmt
                        FROM    @dropAndCreateConstraintsTable
                OPEN C1
                
                FETCH NEXT FROM C1 INTO @DropStatement
                
                WHILE @@FETCH_STATUS = 0
                      BEGIN
                            PRINT 'Executing ' + @DropStatement
                            EXECUTE sp_executesql @DropStatement
                            FETCH NEXT FROM C1 INTO @DropStatement
                      END
                CLOSE C1
                DEALLOCATE C1
                
                /* Truncate all tables in the database in the dbo schema */
                DECLARE @DeleteTableStatement NVARCHAR(MAX)
                DECLARE C2 CURSOR READ_ONLY
                FOR
                        SELECT  'TRUNCATE TABLE [dbo].[' + TABLE_NAME + ']'
                        FROM    INFORMATION_SCHEMA.TABLES
                        WHERE   TABLE_SCHEMA = 'dbo'
                                AND TABLE_TYPE = 'BASE TABLE'
                  /* Change your schema appropriately if you don't want to use dbo */
                OPEN C2
                
                FETCH NEXT FROM C2 INTO @DeleteTableStatement
                
                WHILE @@FETCH_STATUS = 0
                      BEGIN
                            PRINT 'Executing ' + @DeleteTableStatement
                            EXECUTE sp_executesql @DeleteTableStatement
                            FETCH NEXT FROM C2 INTO @DeleteTableStatement
                      END
                CLOSE C2
                DEALLOCATE C2
                
                /* Recreate foreign key constraints  */
                DECLARE C3 CURSOR READ_ONLY
                FOR
                        SELECT  CreateStmt
                        FROM    @dropAndCreateConstraintsTable
                OPEN C3
                
                FETCH NEXT FROM C3 INTO @RecreateStatement
                
                WHILE @@FETCH_STATUS = 0
                      BEGIN
                            PRINT 'Executing ' + @RecreateStatement
                            EXECUTE sp_executesql @RecreateStatement
                            FETCH NEXT FROM C3 INTO @RecreateStatement
                      END
                CLOSE C3
                DEALLOCATE C3
                
                GO
                

                【讨论】:

                • 戴夫,有没有办法在删除和重新创建外键时确定on deleteon update 属性?如果我像您一样忽略它们,它们会恢复以前的设置吗?我有一些设置为cascade,一些设置为set null
                • 未来访问者请注意:他们可以在sys.foreign_keys 表中找到。 (Reference)
                【解决方案9】:
                DECLARE @nombre NVARCHAR(100)
                DECLARE @tablas TABLE(nombre nvarchar(100))
                
                INSERT INTO @tablas
                SELECT t.TABLE_SCHEMA+ '.'+t.TABLE_NAME FROM INFORMATION_SCHEMA.TABLES T
                DECLARE @contador INT=0
                
                SELECT @contador=COUNT(*) FROM INFORMATION_SCHEMA.TABLES
                
                WHILE @contador>0 
                BEGIN
                    SELECT TOP 1 @nombre=nombre FROM @tablas 
                    DECLARE @sql NVARCHAR(500)=''
                    SET @sql =@sql+'Truncate table  '+@nombre
                    EXEC (@sql)
                    SELECT @sql
                    SET @contador=@contador-1   
                    DELETE TOP (1) @tablas 
                END
                

                【讨论】:

                • 稍微描述一下您的查询?
                【解决方案10】:

                当您有外键关系时,接受的答案不太适用。在这种情况下,您必须删除约束并重新创建它们。下面是一个基于答案here

                的存储过程
                CREATE PROCEDURE [dbo].[deleteAllDataFromAllTables] AS
                SET NOCOUNT ON
                
                    DECLARE @dropAndCreateConstraintsTable TABLE ( DropStmt varchar(max) , CreateStmt varchar(max) )
                
                    insert @dropAndCreateConstraintsTable select
                      DropStmt = 'ALTER TABLE [' + ForeignKeys.ForeignTableSchema + 
                          '].[' + ForeignKeys.ForeignTableName + 
                          '] DROP CONSTRAINT [' + ForeignKeys.ForeignKeyName + ']; '
                    ,  CreateStmt = 'ALTER TABLE [' + ForeignKeys.ForeignTableSchema + 
                          '].[' + ForeignKeys.ForeignTableName + 
                          '] WITH CHECK ADD CONSTRAINT [' +  ForeignKeys.ForeignKeyName + 
                          '] FOREIGN KEY([' + ForeignKeys.ForeignTableColumn + 
                          ']) REFERENCES [' + schema_name(sys.objects.schema_id) + '].[' +
                      sys.objects.[name] + ']([' +
                      sys.columns.[name] + ']); '
                     from sys.objects
                      inner join sys.columns
                        on (sys.columns.[object_id] = sys.objects.[object_id])
                      inner join (
                        select sys.foreign_keys.[name] as ForeignKeyName
                         ,schema_name(sys.objects.schema_id) as ForeignTableSchema
                         ,sys.objects.[name] as ForeignTableName
                         ,sys.columns.[name]  as ForeignTableColumn
                         ,sys.foreign_keys.referenced_object_id as referenced_object_id
                         ,sys.foreign_key_columns.referenced_column_id as referenced_column_id
                         from sys.foreign_keys
                          inner join sys.foreign_key_columns
                            on (sys.foreign_key_columns.constraint_object_id
                              = sys.foreign_keys.[object_id])
                          inner join sys.objects
                            on (sys.objects.[object_id]
                              = sys.foreign_keys.parent_object_id)
                            inner join sys.columns
                              on (sys.columns.[object_id]
                                = sys.objects.[object_id])
                               and (sys.columns.column_id
                                = sys.foreign_key_columns.parent_column_id)
                        ) ForeignKeys
                        on (ForeignKeys.referenced_object_id = sys.objects.[object_id])
                         and (ForeignKeys.referenced_column_id = sys.columns.column_id)
                     where (sys.objects.[type] = 'U')
                      and (sys.objects.[name] not in ('sysdiagrams'))
                
                
                    DECLARE @DropStatement nvarchar(max)
                    DECLARE @RecreateStatement nvarchar(max)
                
                    DECLARE C1 CURSOR READ_ONLY
                    FOR
                    SELECT DropStmt from @dropAndCreateConstraintsTable
                    OPEN C1
                
                    FETCH NEXT FROM C1 INTO @DropStatement
                
                    WHILE @@FETCH_STATUS = 0
                    BEGIN
                        PRINT 'Executing ' + @DropStatement
                        execute sp_executesql @DropStatement
                        FETCH NEXT FROM C1 INTO @DropStatement
                    END
                    CLOSE C1
                    DEALLOCATE C1
                
                    DECLARE @DeleteTableStatement nvarchar(max)
                    DECLARE C2 CURSOR READ_ONLY
                    FOR
                    SELECT 'Delete From [dbo].[' + TABLE_NAME + ']' from INFORMATION_SCHEMA.TABLES 
                        WHERE TABLE_SCHEMA = 'dbo' -- Change your schema appropriately.
                    OPEN C2
                
                    FETCH NEXT FROM C2 INTO @DeleteTableStatement
                
                    WHILE @@FETCH_STATUS = 0
                    BEGIN
                        PRINT 'Executing ' + @DeleteTableStatement
                        execute sp_executesql @DeleteTableStatement
                        FETCH NEXT FROM C2 INTO  @DeleteTableStatement
                    END
                    CLOSE C2
                    DEALLOCATE C2
                
                    DECLARE C3 CURSOR READ_ONLY
                    FOR
                    SELECT CreateStmt from @dropAndCreateConstraintsTable
                    OPEN C3
                
                    FETCH NEXT FROM C3 INTO @RecreateStatement
                
                    WHILE @@FETCH_STATUS = 0
                    BEGIN
                        PRINT 'Executing ' + @RecreateStatement
                        execute sp_executesql @RecreateStatement
                        FETCH NEXT FROM C3 INTO  @RecreateStatement
                    END
                    CLOSE C3
                    DEALLOCATE C3
                
                GO
                

                【讨论】:

                  【解决方案11】:

                  我用这个脚本

                  EXEC sp_MSForEachTable ‘ALTER TABLE ? NOCHECK CONSTRAINT ALL’
                  EXEC sp_MSForEachTable ‘DELETE FROM ?’
                  EXEC sp_MSForEachTable ‘ALTER TABLE ? CHECK CONSTRAINT ALL’
                  GO
                  

                  【讨论】:

                  • 爱它。这很棒。我只会添加对dbcc checkident (?, RESEED, 1) 的调用以重置身份(对于那些具有身份的表)。
                  • 在 SQL Server 2012 中,我必须在存储的过程名称之后使用 @command1 = 并且必须在实际命令周围使用双引号而不是单引号。
                  【解决方案12】:

                  您可以像这样使用 sp_MSforeachtable 存储过程:

                  USE MyDatabase
                  EXEC sp_MSforeachtable 'TRUNCATE TABLE ?'
                  

                  请注意,这将删除(通过截断)所有用户表中的所有数据。如果由于外键等原因无法截断,则可以像删除一样运行:

                  USE MyDatabase
                  EXEC sp_MSforeachtable 'DELETE FROM ?'
                  

                  【讨论】:

                  • 如果任何表有外键,这将不起作用。这些将需要删除并重新创建(未禁用/启用)
                  • @Martin 我在您的评论中同时添加了该信息:) 虽然您是对的,除非有级联更新/删除,否则您需要按正确的顺序删除。否则,正如您所提到的,它们必须事先被禁用。
                  • 同意,禁用它们将适用于DELETE,但不适用于TRUNCATE
                  • 多次运行怎么样? :)
                  • @cairnz 这不是一个很好的长期解决方案。如果您尝试自动化此过程,您可能永远不知道它需要提前运行多少次。为此,Boycs 的回答更为有效,因为它会禁用您的外键,清空表,然后重新启用它们的键。
                  猜你喜欢
                  • 2010-09-14
                  • 2015-09-19
                  • 1970-01-01
                  • 1970-01-01
                  • 2011-06-12
                  • 2015-07-31
                  • 1970-01-01
                  • 1970-01-01
                  • 2011-02-19
                  相关资源
                  最近更新 更多