如何使用一个 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 查询从数据库中删除所有表?的主要内容,如果未能解决你的问题,请参考以下文章