【问题标题】:SQL Server 2008 delete all tables under special schemaSQL Server 2008 删除特殊架构下的所有表
【发布时间】:2012-01-19 21:59:31
【问题描述】:

您好,我想知道是否可以删除数据库中在自定义架构下创建的所有表,例如 DBO1...使用一个 sql 查询或特殊脚本。

谢谢

【问题讨论】:

    标签: sql sql-server


    【解决方案1】:

    这将为您生成所有 DROP TABLE 语句并将 SQL 语句打印出来。 然后,您可以在复制和执行之前验证它是否符合您的期望。只要确保你 100% 确定...也许先备份一下 :)

    DECLARE @SqlStatement NVARCHAR(MAX)
    SELECT @SqlStatement = 
        COALESCE(@SqlStatement, N'') + N'DROP TABLE [DBO1].' + QUOTENAME(TABLE_NAME) + N';' + CHAR(13)
    FROM INFORMATION_SCHEMA.TABLES
    WHERE TABLE_SCHEMA = 'DBO1' and TABLE_TYPE = 'BASE TABLE'
    
    PRINT @SqlStatement
    

    【讨论】:

    • 如果他们真的想一口气完成,他们可以在最后执行(或执行 sp_executesql)@SqlStatement。
    • @AdaTheDev 对我来说这生成了一个任意顺序的 drop 语句列表。例如,我不能在孩子面前放弃父母。如果您有外键约束,脚本将不会删除您的表。这就是我的意思
    • 如果您想通过 EXEC 或 exec sp_executesql 执行此操作,您需要将 @SqlStatement 类型更改为 NVARCHAR。
    • 您可以通过多次执行此脚本来删除所有表,尽管有外键约束。
    • 这也将获取视图。您可能需要通过TABLE_TYPE = 'BASE TABLE'进行过滤
    【解决方案2】:

    我知道有些旧线程,但我一直在寻找类似的东西,发现原始答案非常有帮助。也就是说,该脚本还将尝试删除该架构中可能存在的视图并给您一条错误消息,因为您最终会尝试通过发出 DROP TABLE 语句来删除视图。

    我最终写了这个,因为我需要从给定模式中删除所有表、视图、过程和函数。也许不是实现这一点的最优雅的方式,但它对我有用,我想我会分享。

    DECLARE @Sql VARCHAR(MAX)
          , @Schema varchar(20)
    
    SET @Schema = 'Integration' --put your schema name between these quotes
    
    --tables
    SELECT @Sql = COALESCE(@Sql,'') + 'DROP TABLE %SCHEMA%.' + QUOTENAME(TABLE_NAME) + ';' + CHAR(13)
    FROM INFORMATION_SCHEMA.TABLES
    WHERE TABLE_SCHEMA = @Schema
        AND TABLE_TYPE = 'BASE TABLE'
    ORDER BY TABLE_NAME
    
    
    --views
    SELECT @Sql = COALESCE(@Sql,'') + 'DROP VIEW %SCHEMA%.' + QUOTENAME(TABLE_NAME) + ';' + CHAR(13)
    FROM INFORMATION_SCHEMA.TABLES
    WHERE TABLE_SCHEMA = @Schema
        AND TABLE_TYPE = 'VIEW'
    ORDER BY TABLE_NAME
    
    --Procedures
    SELECT @Sql = COALESCE(@Sql,'') + 'DROP PROCEDURE %SCHEMA%.' + QUOTENAME(ROUTINE_NAME) + ';' + CHAR(13)
    FROM INFORMATION_SCHEMA.ROUTINES
    WHERE ROUTINE_SCHEMA = @Schema
        AND ROUTINE_TYPE = 'PROCEDURE'
    ORDER BY ROUTINE_NAME
    
    --Functions
    SELECT @Sql = COALESCE(@Sql,'') + 'DROP FUNCTION %SCHEMA%.' + QUOTENAME(ROUTINE_NAME) + ';' + CHAR(13)
    FROM INFORMATION_SCHEMA.ROUTINES
    WHERE ROUTINE_SCHEMA = @Schema
        AND ROUTINE_TYPE = 'FUNCTION'
    ORDER BY ROUTINE_NAME
    
    
    SELECT @Sql = COALESCE(REPLACE(@Sql,'%SCHEMA%',@Schema), '')
    
    PRINT @Sql
    

    【讨论】:

      【解决方案3】:

      我知道这是一个旧线程,但我认为最简单的方法是使用未记录的 sp_MSforeachtable 存储过程:

      EXEC sp_MSforeachtable
        @command1 = 'DROP TABLE ?'
      , @whereand = 'AND SCHEMA_NAME(schema_id) = ''your_schema_name'' '
      

      可以在here 找到有关此存储过程的详细报告,但如果链接失效,这里是亮点:

      sp_MSforeachtable 是一个存储过程,主要用于将 T-SQL 命令迭代地应用于当前数据库中存在的每个表。
      [...]
      意识到问号(?)它被用作表的替换,并且在执行过程中它会被适当的表名替换。

      @command1、@command2、@command3
      sp_MSforeachtable 存储过程至少需要执行一个命令 (@command1),但它最多允许执行 3 个命令。请注意,它将首先开始执行@command1,然后是@command2 和@command3,最后是每个表。

      @precommand
      使用此参数提供要在@command1 之前执行的命令。设置变量环境或执行任何类型的初始化都很有用。

      @postcommand
      使用此参数提供在所有命令执行成功后要执行的命令。它对于控制和清理过程很有用。

      @replacechar
      默认情况下,表格由问号 (?) 字符表示。这个参数可以让你改变这个字符。

      @whereand
      默认情况下,sp_MSforeachtable 应用于数据库中的所有用户表。使用此参数过滤您要使用的表。在下一节中,我将解释如何过滤表格。

      【讨论】:

      • 绝妙的建议。感谢您的跟进。
      【解决方案4】:

      同样基于@Kevo 的回答,我添加了以下 while 循环来解决我在使用 TSQL Print 语句时遇到的问题。消息字符串最长可达 8,000 个字符。如果大于 8,000,打印语句将截断任何剩余的字符。

      DECLARE @SqlLength int
            , @SqlPosition int = 1
            , @printMaxLength int = 8000
      
      SET @SqlLength = LEN(@Sql)
      
      WHILE (@SqlLength) > @printMaxLength
      BEGIN
          PRINT SUBSTRING(@Sql, @SqlPosition, @printMaxLength)
          SET @SqlLength = @SqlLength - @printMaxLength
          SET @SqlPosition = @SqlPosition + @printMaxLength
      END
      IF (@SqlLength) < @printMaxLength AND (@SqlLength) > 0
      BEGIN
          PRINT SUBSTRING(@Sql, @SqlPosition, @printMaxLength)
      END
      

      【讨论】:

        【解决方案5】:
        select 'DROP TABLE [TABSCHEMA].' + QUOTENAME(TABLE_NAME) + N';' from INFORMATION_SCHEMA.TABLES WHERE TABLE_SCHEMA = 'TABSCHEMA' and TABLE_TYPE = 'BASE TABLE'
        

        【讨论】:

          【解决方案6】:

          在其他答案的基础上,这是一个存储过程 spDropSchema,它删除了架构和架构本身中的所有对象。

          请注意,该过程也会尝试删除序列对象,因此它仅适用于 SQL Server 2012 及更高版本。

          IF EXISTS (SELECT * FROM sysobjects WHERE type = 'P' AND name = 'spDropSchema')
              BEGIN
                  DROP  PROCEDURE  spDropSchema
              END
          GO
          
          CREATE PROCEDURE spDropSchema(@Schema nvarchar(200))
          AS
          
          DECLARE @Sql NVARCHAR(MAX) = '';
          
          --constraints
          SELECT @Sql = @Sql + 'ALTER TABLE '+ QUOTENAME(@Schema) + '.' + QUOTENAME(t.name) + ' DROP CONSTRAINT ' + QUOTENAME(f.name)  + ';' + CHAR(13)
          FROM sys.tables t 
              inner join sys.foreign_keys f on f.parent_object_id = t.object_id 
              inner join sys.schemas s on t.schema_id = s.schema_id
          WHERE s.name = @Schema
          ORDER BY t.name;
          
          --tables
          SELECT @Sql = @Sql + 'DROP TABLE '+ QUOTENAME(@Schema) +'.' + QUOTENAME(TABLE_NAME) + ';' + CHAR(13)
          FROM INFORMATION_SCHEMA.TABLES
          WHERE TABLE_SCHEMA = @Schema AND TABLE_TYPE = 'BASE TABLE'
          ORDER BY TABLE_NAME
          
          --views
          SELECT @Sql = @Sql + 'DROP VIEW '+ QUOTENAME(@Schema) +'.' + QUOTENAME(TABLE_NAME) + ';' + CHAR(13)
          FROM INFORMATION_SCHEMA.TABLES
          WHERE TABLE_SCHEMA = @Schema AND TABLE_TYPE = 'VIEW'
          ORDER BY TABLE_NAME
          
          --procedures
          SELECT @Sql = @Sql + 'DROP PROCEDURE '+ QUOTENAME(@Schema) +'.' + QUOTENAME(ROUTINE_NAME) + ';' + CHAR(13)
          FROM INFORMATION_SCHEMA.ROUTINES
          WHERE ROUTINE_SCHEMA = @Schema AND ROUTINE_TYPE = 'PROCEDURE'
          ORDER BY ROUTINE_NAME
          
          --functions
          SELECT @Sql = @Sql + 'DROP FUNCTION '+ QUOTENAME(@Schema) +'.' + QUOTENAME(ROUTINE_NAME) + ';' + CHAR(13)
          FROM INFORMATION_SCHEMA.ROUTINES
          WHERE ROUTINE_SCHEMA = @Schema AND ROUTINE_TYPE = 'FUNCTION'
          ORDER BY ROUTINE_NAME
          
          --sequences
          SELECT @Sql = @Sql + 'DROP SEQUENCE '+ QUOTENAME(@Schema) +'.' + QUOTENAME(SEQUENCE_NAME) + ';' + CHAR(13)
          FROM INFORMATION_SCHEMA.SEQUENCES
          WHERE SEQUENCE_SCHEMA = @Schema
          ORDER BY SEQUENCE_NAME
          
          --types
          SELECT @Sql = @Sql + 'DROP TYPE ' + QUOTENAME(@Schema) + '.' + QUOTENAME(t.name) + ';' + CHAR(13)
          FROM sys.types t
              INNER JOIN sys.schemas s ON t.schema_id = s.schema_id
          WHERE t.is_user_defined = 1 AND
              s.name  = @Schema
          ORDER BY s.name
          
          SELECT @Sql = @Sql + 'DROP SCHEMA '+ QUOTENAME(@Schema) + ';' + CHAR(13)
          
          EXECUTE sp_executesql @Sql
          
          GO
          

          【讨论】:

          • 有时您也必须删除用户定义的类型。可以通过SELECT * FROM sys.types where is_user_defined = 1 找到它们
          【解决方案7】:

          以防万一它对某人有所帮助,我将其作为存储过程添加到主数据库中,以便在任何数据库/架构上方便地使用它。

          可以这样调用:

          EXEC master.dbo.dropTablesInSchema 'my_db', 'dbo
          

          存储过程创建脚本:

          CREATE PROC [master].[dbo].[dropTablesInSchema]
              @db nvarchar(max),
              @schema nvarchar(max)
          AS
          BEGIN
              DECLARE @Tables TABLE (name nvarchar(max))
              INSERT INTO @Tables
              EXEC ('SELECT TABLE_NAME FROM [' + @db + '].INFORMATION_SCHEMA.TABLES WHERE TABLE_SCHEMA = ''' + @schema + ''' and TABLE_TYPE =''BASE TABLE''')
          
              DECLARE @SqlStatement NVARCHAR(MAX)
              SELECT @SqlStatement = 
                  COALESCE(@SqlStatement, N'') + N'DROP TABLE [' + @db + '].[' + @schema + '].' + QUOTENAME(NAME) + N';' + CHAR(13)
              FROM @Tables
          
              EXEC(@SqlStatement)
          
          END
          

          【讨论】:

            【解决方案8】:

            我将@raider33 和@Kevo 的答案组合成一个直接执行的解决方案。

            DECLARE @SqlStatement NVARCHAR(MAX)
            DECLARE @schema varchar(30) = 'SCHEMA_NAME';
            
            select @SqlStatement = COALESCE(@SqlStatement,'') + 'ALTER TABLE '+@schema+'.' + t.name + ' drop constraint ' + 
            OBJECT_NAME(d.constraint_object_id)  + ';' + CHAR(13) + CHAR(10)
            from sys.tables t 
                join sys.foreign_key_columns d on d.parent_object_id = t.object_id 
                inner join sys.schemas s on t.schema_id = s.schema_id
            where s.name = @schema
            ORDER BY t.name;
            
            SELECT @SqlStatement += 
                COALESCE(@SqlStatement, '') + 'DROP TABLE ' + @schema +'.'+ QUOTENAME(TABLE_NAME) + ';'  + CHAR(13) + CHAR(10)
            FROM INFORMATION_SCHEMA.TABLES
            WHERE TABLE_SCHEMA = @schema
            
            EXECUTE sp_executesql @SqlStatement
            

            【讨论】:

              【解决方案9】:

              chris LB's answer 的基础上,我添加了

              GROUP BY d.constraint_object_id, t.name
              

              因为我在查询中看到重复的约束删除。 constraint_object_id 是 FK 约束 ID,如 https://msdn.microsoft.com/en-us/library/ms186306.aspx 中所述

              DECLARE @SqlStatement NVARCHAR(MAX),
                      @Schema NVARCHAR(20)
              
              SET @Schema = 'aa'
              
              SELECT @SqlStatement = 
                  COALESCE(@SqlStatement,'') + 'ALTER TABLE '+@Schema+'.' + t.name + ' DROP CONSTRAINT ' + 
                  OBJECT_NAME(d.constraint_object_id)  + ';' + CHAR(13) + CHAR(10)
              FROM sys.tables t
                  JOIN sys.foreign_key_columns d on t.object_id = d.parent_object_id 
                  INNER JOIN sys.schemas s on t.schema_id = s.schema_id
              WHERE s.name = @Schema
              GROUP BY d.constraint_object_id, t.name
              ORDER BY t.name;
              

              【讨论】:

                【解决方案10】:

                基于@Kevo 的回答,我添加了以下内容以在删除表之前删除所有外键约束。我只在 SQL2008 R2 上测试过

                select @Sql = COALESCE(@Sql,'') + 'ALTER TABLE %SCHEMA%.' + t.name + ' drop constraint ' + 
                OBJECT_NAME(d.constraint_object_id)  + ';' + CHAR(13)
                from sys.tables t 
                    join sys.foreign_key_columns d on d.parent_object_id = t.object_id 
                    inner join sys.schemas s on t.schema_id = s.schema_id
                where s.name = @Schema
                ORDER BY t.name;
                

                【讨论】:

                  【解决方案11】:

                  这将生成所有 DROP TABLE 和 DROP VIEW 并检查是否存在。

                  DECLARE @SqlStatement NVARCHAR(MAX)
                  
                  SELECT @SqlStatement = 
                  COALESCE(@SqlStatement, N'') + N'IF  EXISTS (SELECT * FROM sys.objects WHERE object_id = OBJECT_ID(N'''+'['+TABLE_SCHEMA+'].' + QUOTENAME(TABLE_NAME) +''' )' + CHAR(13)+
                   '  DROP '+ TABLE_TYPE +' ['+TABLE_SCHEMA+'].' + QUOTENAME(TABLE_NAME) + N';' + CHAR(13)
                  FROM INFORMATION_SCHEMA.TABLES
                  WHERE TABLE_SCHEMA in ('SCHEMA1','SCHEMA2','SCHEMA13' )
                  ORDER BY TABLE_SCHEMA   
                  
                  PRINT  REPLACE(@SqlStatement,'DROP BASE TABLE ','DROP TABLE ') 
                  GO
                  

                  【讨论】:

                    【解决方案12】:

                    删除 schema 中的所有表,可以修改为返回表的任何子集。

                    declare @schema varchar(10) = 'temp' 
                    declare @max_number_of_tables int = 1000
                    declare @sql nvarchar(max)
                    declare @index int = 0
                    
                    
                    while (
                    select count(*)
                    from
                        sys.objects obj
                        join sys.schemas s
                            on (s.schema_id=obj.schema_id)
                    where
                        s.name= @schema 
                        and obj.type = 'U'
                        AND obj.is_ms_shipped = 0x0) > 0 and @index < @max_number_of_tables
                    begin
                      set @index = @index+1
                    
                      select top 1
                        @sql = N'DROP TABLE [' + @schema + '].[' + obj.name + ']'
                      from
                        sys.objects obj
                        join sys.schemas s
                            on (s.schema_id=obj.schema_id)
                      where
                        s.name = @schema
                        and obj.type = 'U'
                        AND obj.is_ms_shipped = 0x0
                      order by obj.name
                    
                      print @sql
                    
                      execute(@sql)
                    end
                    

                    【讨论】:

                      【解决方案13】:

                      修改已接受的答案,只需复制粘贴即可。

                      db 更改为您的数据库并将@dbSchema 设置为您的架构。

                      USE db -- CHANGE TO YOUR DB
                      GO
                      
                      DECLARE @dbSchema NVARCHAR(200);
                      SET @dbSchema = 'dbo'  -- CHANGE TO YOUR SCHEMA
                      
                      DECLARE @SqlStatement NVARCHAR(MAX)
                      SELECT @SqlStatement =
                          COALESCE(@SqlStatement, N'') + N'DROP TABLE ' +'[' + @dbSchema +']' + '.' + QUOTENAME(TABLE_NAME) + N';' + CHAR(13)
                      FROM INFORMATION_SCHEMA.TABLES
                      WHERE TABLE_SCHEMA = @dbSchema and TABLE_TYPE = 'BASE TABLE'
                      
                      EXEC sp_executesql @SqlStatement
                      

                      【讨论】:

                        最近更新 更多