如何使用一个 SQL 查询从数据库中删除所有表?

Posted

技术标签:

【中文标题】如何使用一个 SQL 查询从数据库中删除所有表?【英文标题】:How to drop all tables from a database with one SQL query? 【发布时间】:2015-02-20 18:40:50 【问题描述】:

我不想输入所有表的名称来删除所有表。一个查询可以吗?

【问题讨论】:

一些快速谷歌搜索揭示了这一点:***.com/questions/11053116/… -虽然(对于 SQLServer)这可能更有用:***.com/questions/536350/… 使用正确的用户名,这可能会自动发生 (obligatory xkcd link)。 数据库中的表有外键吗?如果是这样,您需要考虑到这一点,并在尝试删除表之前删除它们。 请记住,如果您有架构绑定对象,则不能删除表。 【参考方案1】:

使用INFORMATION_SCHEMA.TABLES 视图获取表列表。在 select 语句中生成 Drop 脚本并使用 Dynamic SQL 将其删除:

DECLARE @sql NVARCHAR(max)=''

SELECT @sql += ' Drop table ' + QUOTENAME(TABLE_SCHEMA) + '.'+ QUOTENAME(TABLE_NAME) + '; '
FROM   INFORMATION_SCHEMA.TABLES
WHERE  TABLE_TYPE = 'BASE TABLE'

Exec Sp_executesql @sql

Sys.Tables版本

DECLARE @sql NVARCHAR(max)=''

SELECT @sql += ' Drop table ' + QUOTENAME(s.NAME) + '.' + QUOTENAME(t.NAME) + '; '
FROM   sys.tables t
       JOIN sys.schemas s
         ON t.[schema_id] = s.[schema_id]
WHERE  t.type = 'U'

Exec sp_executesql @sql

注意:如果您在表之间定义了任何foreign Keys,则首先运行以下查询以禁用您的数据库中存在的所有foreign keys

EXEC sp_msforeachtable "ALTER TABLE ? NOCHECK CONSTRAINT all"

欲了解更多信息,check here

【讨论】:

(不是我的反对意见)...如果不需要跨 rdbms 的可移植性,我通常会坚持使用 [sys] 模式视图。 ***.com/a/3654313/251174 另见sqlblog.com/blogs/aaron_bertrand/archive/2011/11/03/… @DoubleA - 这很简单。首先是为我的数据库中的所有表构建 Drop 语句并将其存储到一个变量中。要检查这一点,您可以在exec 之前使用Print @sql。然后通过sp_executesql 执行动态构建的 drop 语句 如果您使用的是 Azure,则 sp_msforeachtable 不可用。我从@Aaron Bertrand 找到了这个甜蜜的金块来删除所有 FK 约束。这个答案真的很好用。 dba.stackexchange.com/questions/90033/… 如果 sp_msforeachtable 不可用,您也可以多次运行 delete 查询,因为依赖于其他表的表随后会被删除:)【参考方案2】:

如果你只想使用一个 SQL 查询来删除所有表,你可以使用这个:

EXEC sp_MSforeachtable @command1 = "DROP TABLE ?"

这是一个隐藏在 sql server 中的存储过程,将针对你连接的数据库中的每个表执行。

注意:由于依赖关系,您可能需要执行几次查询才能删除所有表。

注意2:为避免出现第一个注释,在运行查询之前,首先检查是否存在与任何表的外键关系。如果只有disable 外键约束,请运行以下查询:

EXEC sp_msforeachtable "ALTER TABLE ? NOCHECK CONSTRAINT all"

【讨论】:

我在我的 Azure SQL 数据库上尝试过,但没有成功。然而,上述答案(由 Prdp 提供)奏效了。 附带说明,我需要在删除所有表之前多次运行第一个命令,但它工作正常。 @Thatshowweroll 这可能是因为表的依赖关系。如果一个表有其他依赖于它的表,则无法删除。 @RageAgainstTheMachine 是的,它肯定来自具有多个交叉依赖关系的表。我想通知用户多次运行它,错误不是问题。运行第一个命令 3-4 次,然后运行第二个命令 1 次和 BOM。它就像魅力一样! @KyleVassella 是的,这只会在您打开控制台的数据库上执行【参考方案3】:

如果你不想输入,你可以用这个来创建语句:

USE Databasename

SELECT  'DROP TABLE [' + name + '];'
FROM    sys.tables

然后复制并粘贴到一个新的 SSMS 窗口中运行它。

【讨论】:

表名应该包含在 [ ] 中,但即使在 Azure 上也能很好地工作 我们也可以使用QUOTENAME,看起来很整洁。 'DROP TABLE ' + QUOTENAME(name) + ';' 我们也可以使用这个顺序来避免删除时出现约束问题。按 create_date desc 排序【参考方案4】:

您还可以使用以下脚本删除所有内容,包括以下内容:

非系统存储过程 观看次数 功能 外键约束 主键约束 system_versioning 表格

https://michaelreichenbach.de/how-to-drop-everything-in-a-mssql-database/

/* Drop all non-system stored procs */
DECLARE @name VARCHAR(128)
DECLARE @SQL VARCHAR(254)

SELECT @name = (SELECT TOP 1 [name] FROM sysobjects WHERE [type] = 'P' AND category = 0 ORDER BY [name])

WHILE @name is not null
BEGIN
    SELECT @SQL = 'DROP PROCEDURE [dbo].[' + RTRIM(@name) +']'
    EXEC (@SQL)
    PRINT 'Dropped Procedure: ' + @name
    SELECT @name = (SELECT TOP 1 [name] FROM sysobjects WHERE [type] = 'P' AND category = 0 AND [name] > @name ORDER BY [name])
END
GO

/* Drop all views */
DECLARE @name VARCHAR(128)
DECLARE @SQL VARCHAR(254)

SELECT @name = (SELECT TOP 1 [name] FROM sysobjects WHERE [type] = 'V' AND category = 0 ORDER BY [name])

WHILE @name IS NOT NULL
BEGIN
    SELECT @SQL = 'DROP VIEW [dbo].[' + RTRIM(@name) +']'
    EXEC (@SQL)
    PRINT 'Dropped View: ' + @name
    SELECT @name = (SELECT TOP 1 [name] FROM sysobjects WHERE [type] = 'V' AND category = 0 AND [name] > @name ORDER BY [name])
END
GO

/* Drop all functions */
DECLARE @name VARCHAR(128)
DECLARE @SQL VARCHAR(254)

SELECT @name = (SELECT TOP 1 [name] FROM sysobjects WHERE [type] IN (N'FN', N'IF', N'TF', N'FS', N'FT') AND category = 0 ORDER BY [name])

WHILE @name IS NOT NULL
BEGIN
    SELECT @SQL = 'DROP FUNCTION [dbo].[' + RTRIM(@name) +']'
    EXEC (@SQL)
    PRINT 'Dropped Function: ' + @name
    SELECT @name = (SELECT TOP 1 [name] FROM sysobjects WHERE [type] IN (N'FN', N'IF', N'TF', N'FS', N'FT') AND category = 0 AND [name] > @name ORDER BY [name])
END
GO

/* Drop all Foreign Key constraints */
DECLARE @name VARCHAR(128)
DECLARE @constraint VARCHAR(254)
DECLARE @SQL VARCHAR(254)

SELECT @name = (SELECT TOP 1 TABLE_NAME FROM INFORMATION_SCHEMA.TABLE_CONSTRAINTS WHERE constraint_catalog=DB_NAME() AND CONSTRAINT_TYPE = 'FOREIGN KEY' ORDER BY TABLE_NAME)

WHILE @name is not null
BEGIN
    SELECT @constraint = (SELECT TOP 1 CONSTRAINT_NAME FROM INFORMATION_SCHEMA.TABLE_CONSTRAINTS WHERE constraint_catalog=DB_NAME() AND CONSTRAINT_TYPE = 'FOREIGN KEY' AND TABLE_NAME = @name ORDER BY CONSTRAINT_NAME)
    WHILE @constraint IS NOT NULL
    BEGIN
        SELECT @SQL = 'ALTER TABLE [dbo].[' + RTRIM(@name) +'] DROP CONSTRAINT [' + RTRIM(@constraint) +']'
        EXEC (@SQL)
        PRINT 'Dropped FK Constraint: ' + @constraint + ' on ' + @name
        SELECT @constraint = (SELECT TOP 1 CONSTRAINT_NAME FROM INFORMATION_SCHEMA.TABLE_CONSTRAINTS WHERE constraint_catalog=DB_NAME() AND CONSTRAINT_TYPE = 'FOREIGN KEY' AND CONSTRAINT_NAME <> @constraint AND TABLE_NAME = @name ORDER BY CONSTRAINT_NAME)
    END
SELECT @name = (SELECT TOP 1 TABLE_NAME FROM INFORMATION_SCHEMA.TABLE_CONSTRAINTS WHERE constraint_catalog=DB_NAME() AND CONSTRAINT_TYPE = 'FOREIGN KEY' ORDER BY TABLE_NAME)
END
GO

/* Drop all Primary Key constraints */
DECLARE @name VARCHAR(128)
DECLARE @constraint VARCHAR(254)
DECLARE @SQL VARCHAR(254)

SELECT @name = (SELECT TOP 1 TABLE_NAME FROM INFORMATION_SCHEMA.TABLE_CONSTRAINTS WHERE constraint_catalog=DB_NAME() AND CONSTRAINT_TYPE = 'PRIMARY KEY' ORDER BY TABLE_NAME)

WHILE @name IS NOT NULL
BEGIN
    SELECT @constraint = (SELECT TOP 1 CONSTRAINT_NAME FROM INFORMATION_SCHEMA.TABLE_CONSTRAINTS WHERE constraint_catalog=DB_NAME() AND CONSTRAINT_TYPE = 'PRIMARY KEY' AND TABLE_NAME = @name ORDER BY CONSTRAINT_NAME)
    WHILE @constraint is not null
    BEGIN
        SELECT @SQL = 'ALTER TABLE [dbo].[' + RTRIM(@name) +'] DROP CONSTRAINT [' + RTRIM(@constraint)+']'
        EXEC (@SQL)
        PRINT 'Dropped PK Constraint: ' + @constraint + ' on ' + @name
        SELECT @constraint = (SELECT TOP 1 CONSTRAINT_NAME FROM INFORMATION_SCHEMA.TABLE_CONSTRAINTS WHERE constraint_catalog=DB_NAME() AND CONSTRAINT_TYPE = 'PRIMARY KEY' AND CONSTRAINT_NAME <> @constraint AND TABLE_NAME = @name ORDER BY CONSTRAINT_NAME)
    END
SELECT @name = (SELECT TOP 1 TABLE_NAME FROM INFORMATION_SCHEMA.TABLE_CONSTRAINTS WHERE constraint_catalog=DB_NAME() AND CONSTRAINT_TYPE = 'PRIMARY KEY' ORDER BY TABLE_NAME)
END
GO

/* Remove system versioning */
DECLARE @name VARCHAR(128)
DECLARE @SQL VARCHAR(254)

SELECT @name = (SELECT TOP 1 [name] FROM sysobjects WHERE [type] = 'U' AND category = 0 ORDER BY [name])

WHILE @name IS NOT NULL
BEGIN
    IF OBJECTPROPERTY(OBJECT_ID(' + @name + '), 'TableTemporalType') = 2 
        SELECT @SQL = 'ALTER TABLE [dbo].[' + RTRIM(@name) +'] SET (SYSTEM_VERSIONING = OFF); ALTER TABLE [dbo].[' + RTRIM(@name) + '] DROP PERIOD FOR SYSTEM_TIME;'
        EXEC (@SQL)
        PRINT 'System Versioning Disabled for Table: ' + @name
        SELECT @name = (SELECT TOP 1 [name] FROM sysobjects WHERE [type] = 'U' AND category = 0 AND [name] > @name ORDER BY [name])
END
GO

/* Drop all tables */
DECLARE @name VARCHAR(128)
DECLARE @SQL VARCHAR(254)

SELECT @name = (SELECT TOP 1 [name] FROM sysobjects WHERE [type] = 'U' AND category = 0 ORDER BY [name])

WHILE @name IS NOT NULL
BEGIN
    SELECT @SQL = 'DROP TABLE [dbo].[' + RTRIM(@name) +']'
    EXEC (@SQL)
    PRINT 'Dropped Table: ' + @name
    SELECT @name = (SELECT TOP 1 [name] FROM sysobjects WHERE [type] = 'U' AND category = 0 AND [name] > @name ORDER BY [name])
END
GO

【讨论】:

抱歉,此脚本不适用于多模式。您已硬编码“[dbo]”。在脚本的多行中。 运行良好.. 删除表格的最佳脚本。【参考方案5】:

最简单的方法是删除整个数据库并重新创建:

drop database db_name
create database db_name

就是这样。

【讨论】:

:) 至少对我来说删除所有表的目的是因为无法删除数据库 不要在公司的数据库上运行这个命令。或者准备好找另一份工作。 @FarazDurrani 简单的人,删除所有表对于 PROD db 似乎也不是一笔交易。 小心。这将清除与表关联的所有其他系统对象,如过程、视图等。【参考方案6】:

作为 Dave.Gugg 回答的后续,这将是获取 mysql 中所有 DROP TABLE 行所需的代码:

SELECT CONCAT('DROP TABLE ', TABLE_NAME, ';')
FROM INFORMATION_SCHEMA.tables
WHERE TABLE_SCHEMA = 'your_database_name'

【讨论】:

我知道原始发帖人用“sql-server”标记了这个问题,但这可能对希望在 MySQL 中执行此操作的人有用。事实上,当我在谷歌上搜索这个问题的 MySQL 解决方案时,我发现了这个问题,所以我现在在这里分享我在阅读其中一个答案后提出的解决方案。【参考方案7】:

我只需对@NoDisplayName 的答案做一个小改动,在TABLE_NAME 列上使用QUOTENAME(),还包括TABLE_SCHEMA 列,以防止表不在dbo 架构中。

DECLARE @sql nvarchar(max) = '';

SELECT @sql += 'DROP TABLE ' + QUOTENAME([TABLE_SCHEMA]) + '.' + QUOTENAME([TABLE_NAME]) + ';'
FROM [INFORMATION_SCHEMA].[TABLES]
WHERE [TABLE_TYPE] = 'BASE TABLE';

EXEC SP_EXECUTESQL @sql;

或使用sys 模式视图(根据@swasheck 的评论):

DECLARE @sql nvarchar(max) = '';

SELECT @sql += 'DROP TABLE ' + QUOTENAME([S].[name]) + '.' + QUOTENAME([T].[name]) + ';'
FROM [sys].[tables] AS [T]
INNER JOIN [sys].[schemas] AS [S] ON ([T].[schema_id] = [S].[schema_id])
WHERE [T].[type] = 'U' AND [T].[is_ms_shipped] = 0;

EXEC SP_EXECUTESQL @sql;

【讨论】:

如果不需要跨 rdbms 的可移植性,我通常会坚持使用 [sys] 模式视图。 ***.com/a/3654313/251174 @swasheck 感谢您提供非常有趣的链接。我已经使用 sys 架构视图更新了答案。 您可以使用 Schema_name() 函数来获取架构名称,而不是加入msdn.microsoft.com/en-us/library/ms175068.aspx @NoDisplayName 仅仅因为你可以,并不意味着你应该...blogs.sqlsentry.com/aaronbertrand/… @AaronBertrand - 我认为这可能是一个更好的方法。感谢您指出。【参考方案8】:

如果其他人对最佳答案的解决方案(包括禁用外键)有疑问,这里是我的另一个解决方案

-- CLEAN DB
USE [DB_NAME]
    EXEC sp_MSForEachTable 'ALTER TABLE ? NOCHECK CONSTRAINT ALL'
    EXEC sp_MSForEachTable 'DELETE FROM ?'

    DECLARE @Sql NVARCHAR(500) DECLARE @Cursor CURSOR
    SET @Cursor = CURSOR FAST_FORWARD FOR

    SELECT DISTINCT sql = 'ALTER TABLE [' + tc2.TABLE_NAME + '] DROP [' + rc1.CONSTRAINT_NAME + ']'
    FROM INFORMATION_SCHEMA.REFERENTIAL_CONSTRAINTS rc1
    LEFT JOIN INFORMATION_SCHEMA.TABLE_CONSTRAINTS tc2 ON tc2.CONSTRAINT_NAME =rc1.CONSTRAINT_NAME
    OPEN @Cursor FETCH NEXT FROM @Cursor INTO @Sql
    WHILE (@@FETCH_STATUS = 0)
      BEGIN
        Exec SP_EXECUTESQL @Sql
        FETCH NEXT 
        FROM @Cursor INTO @Sql
      END
    CLOSE @Cursor DEALLOCATE @Cursor
    GO

    EXEC sp_MSForEachTable 'DROP TABLE ?'
    GO

    EXEC sp_MSForEachTable 'ALTER TABLE ? WITH CHECK CHECK CONSTRAINT ALL'

【讨论】:

【参考方案9】:

不是 1 条查询,仍然很短很甜:

-- Disable all referential integrity constraints
EXEC sp_msforeachtable 'ALTER TABLE ? NOCHECK CONSTRAINT ALL'
GO

-- Drop all PKs and FKs
declare @sql nvarchar(max)
SELECT @sql = STUFF((SELECT '; ' + 'ALTER TABLE ' + Table_Name  +'  drop constraint ' + Constraint_Name  from Information_Schema.CONSTRAINT_TABLE_USAGE ORDER BY Constraint_Name FOR XML PATH('')),1,1,'')
EXECUTE (@sql)
GO

-- Drop all tables
EXEC sp_msforeachtable 'DROP TABLE ?'
GO

【讨论】:

【参考方案10】:

使用以下脚本将drop全部constraints

DECLARE @sql NVARCHAR(max)=''

SELECT @sql += ' ALTER TABLE ' + QUOTENAME(TABLE_SCHEMA) + '.'+ QUOTENAME(TABLE_NAME) +    ' NOCHECK CONSTRAINT all; '
FROM   INFORMATION_SCHEMA.TABLES
WHERE  TABLE_TYPE = 'BASE TABLE'

Exec Sp_executesql @sql

然后运行以下命令删除所有表:

select @sql='';

SELECT @sql += ' Drop table ' + QUOTENAME(TABLE_SCHEMA) + '.'+ QUOTENAME(TABLE_NAME) + '; '
FROM   INFORMATION_SCHEMA.TABLES
WHERE  TABLE_TYPE = 'BASE TABLE'

Exec Sp_executesql @sql

这在 'sp_msforeachtable' 不可用的 Azure SQL 数据库中对我有用!

【讨论】:

【参考方案11】:

我知道这个问题很老了,但每次我需要这段代码时..顺便说一下,如果你有表和视图以及函数和过程,你可以通过这个脚本将它全部删除.. 那我为什么要发布这个脚本??因为如果你删除所有表,你将需要删除所有视图,如果你有函数和过程,你也需要删除它 我希望它会帮助别人

DECLARE @sql NVARCHAR(max)=''

 SELECT @sql += ' Drop table ' + QUOTENAME(TABLE_SCHEMA) + '.'+ QUOTENAME(TABLE_NAME) 
+ '; '
FROM   INFORMATION_SCHEMA.TABLES
WHERE  TABLE_TYPE = 'BASE TABLE'

Exec Sp_executesql @sql


 DECLARE @sql VARCHAR(MAX) = ''
    , @crlf VARCHAR(2) = CHAR(13) + CHAR(10) ;

 SELECT @sql = @sql + 'DROP VIEW ' + QUOTENAME(SCHEMA_NAME(schema_id)) + '.' + 
 QUOTENAME(v.name) +';' + @crlf
 FROM   sys.views v

 PRINT @sql;
 EXEC(@sql);

 declare @procName varchar(500)
 declare cur cursor 

 for select [name] from sys.objects where type = 'p'
 open cur
 fetch next from cur into @procName
 while @@fetch_status = 0
 begin
  exec('drop procedure [' + @procName + ']')
fetch next from cur into @procName
 end
  close cur
  deallocate cur

  Declare @sql NVARCHAR(MAX) = N'';

    SELECT @sql = @sql + N' DROP FUNCTION ' 
               + QUOTENAME(SCHEMA_NAME(schema_id)) 
               + N'.' + QUOTENAME(name)
    FROM sys.objects
  WHERE type_desc LIKE '%FUNCTION%';

   Exec sp_executesql @sql
  GO

【讨论】:

【参考方案12】:

对我来说,我只是这样做


DECLARE @cnt INT = 0;

WHILE @cnt < 10 --Change this if all tables are not dropped with one run
BEGIN
SET @cnt = @cnt + 1;
EXEC sp_MSforeachtable @command1 = "DROP TABLE ?"
END

【讨论】:

【参考方案13】:

如果你使用 oracle 或 sqlite,我会为所有表循环:

FOR i IN (SELECT ut.table_name
              FROM USER_TABLES ut) LOOP
    EXECUTE IMMEDIATE 'drop table '|| i.table_name ||' CASCADE CONSTRAINTS ';
  END LOOP;

【讨论】:

以上是关于如何使用一个 SQL 查询从数据库中删除所有表?的主要内容,如果未能解决你的问题,请参考以下文章

在试听中如何用SQL选中从表选取所有列

如何用SQL语句求oracle 数据库所有表的行数?

sql存储过程从一张表中查询到的值作为另一张表的新的字段

SQL数据库,如何查询数据库内含有某一列(某字段,如name)的所有表

SQL语句如何查询倒数第二项数据

sql语言如何查询一条记录中含有两个关键字?