我试图写一个脚本,将完全清空SQL Server数据库。这是我目前所拥有的:
USE [dbname]
GO
EXEC sp_msforeachtable 'ALTER TABLE ? NOCHECK CONSTRAINT all'
EXEC sp_msforeachtable 'DELETE ?'
当我在管理工作室运行它时,我得到:
命令执行成功。
但当我刷新表列表时,它们都还在那里。我做错了什么?
我试图写一个脚本,将完全清空SQL Server数据库。这是我目前所拥有的:
USE [dbname]
GO
EXEC sp_msforeachtable 'ALTER TABLE ? NOCHECK CONSTRAINT all'
EXEC sp_msforeachtable 'DELETE ?'
当我在管理工作室运行它时,我得到:
命令执行成功。
但当我刷新表列表时,它们都还在那里。我做错了什么?
当前回答
我知道这是一篇老文章了,但我已经在大量的数据库上尝试了所有的答案,我发现它们有时都有效,但不是所有时间都适用于SQL Server的各种(我只能假设)怪癖。
最后我想到了这个。我在任何地方都测试过这个(一般来说),它是有效的(没有任何隐藏的存储过程)。
主要用于SQL Server 2014。(但我尝试过的大多数其他版本似乎也很好)。
我尝试过while循环和null等,游标和其他各种形式,但它们似乎总是在一些数据库上失败,而不是其他没有明显的原因。
获得一个计数并使用它进行迭代似乎总是适用于我测试的所有内容。
USE [****YOUR_DATABASE****]
GO
SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO
-- Drop all referential integrity constraints --
-- Drop all Primary Key constraints. --
DECLARE @sql NVARCHAR(296)
DECLARE @table_name VARCHAR(128)
DECLARE @constraint_name VARCHAR(128)
SET @constraint_name = ''
DECLARE @row_number INT
SELECT @row_number = Count(*) FROM INFORMATION_SCHEMA.REFERENTIAL_CONSTRAINTS rc1
LEFT JOIN INFORMATION_SCHEMA.TABLE_CONSTRAINTS tc2 ON tc2.CONSTRAINT_NAME = rc1.CONSTRAINT_NAME
WHILE @row_number > 0
BEGIN
BEGIN
SELECT TOP 1 @table_name = tc2.TABLE_NAME, @constraint_name = rc1.CONSTRAINT_NAME FROM INFORMATION_SCHEMA.REFERENTIAL_CONSTRAINTS rc1
LEFT JOIN INFORMATION_SCHEMA.TABLE_CONSTRAINTS tc2 ON tc2.CONSTRAINT_NAME = rc1.CONSTRAINT_NAME
AND rc1.CONSTRAINT_NAME > @constraint_name
ORDER BY rc1.CONSTRAINT_NAME
SELECT @sql = 'ALTER TABLE [dbo].[' + RTRIM(@table_name) +'] DROP CONSTRAINT [' + RTRIM(@constraint_name)+']'
EXEC (@sql)
PRINT 'Dropped Constraint: ' + @constraint_name + ' on ' + @table_name
SET @row_number = @row_number - 1
END
END
GO
-- Drop all tables --
DECLARE @sql NVARCHAR(156)
DECLARE @name VARCHAR(128)
SET @name = ''
DECLARE @row_number INT
SELECT @row_number = Count(*) FROM sysobjects WHERE [type] = 'U' AND category = 0
WHILE @row_number > 0
BEGIN
SELECT @name = (SELECT TOP 1 [name] FROM sysobjects WHERE [type] = 'U' AND category = 0 AND [name] > @name ORDER BY [name])
SELECT @sql = 'DROP TABLE [dbo].[' + RTRIM(@name) +']'
EXEC (@sql)
PRINT 'Dropped Table: ' + @name
SET @row_number = @row_number - 1
END
GO
其他回答
Azure SQL +表(带约束)的模式与dbo + ipv6_database_firewall_rules条件不同。
这是一个小扩展https://stackoverflow.com/a/43128914/4510954的答案。
DECLARE @sql NVARCHAR(2000)
WHILE(EXISTS(SELECT 1 from INFORMATION_SCHEMA.TABLE_CONSTRAINTS WHERE CONSTRAINT_TYPE='FOREIGN KEY'))
BEGIN
SELECT TOP 1 @sql=('ALTER TABLE ' + CONSTRAINT_SCHEMA + '.[' + TABLE_NAME + '] DROP CONSTRAINT [' + CONSTRAINT_NAME + ']')
FROM INFORMATION_SCHEMA.TABLE_CONSTRAINTS
WHERE CONSTRAINT_TYPE = 'FOREIGN KEY'
EXEC(@sql)
PRINT @sql
END
WHILE(EXISTS(SELECT * from INFORMATION_SCHEMA.TABLES WHERE TABLE_NAME != '__MigrationHistory' AND TABLE_NAME != 'database_firewall_rules' AND TABLE_NAME != 'ipv6_database_firewall_rules'))
BEGIN
SELECT TOP 1 @sql=('DROP TABLE ' + CONSTRAINT_SCHEMA + '.[' + TABLE_NAME + ']')
FROM INFORMATION_SCHEMA.TABLE_CONSTRAINTS
WHERE TABLE_NAME != '__MigrationHistory' AND TABLE_NAME != 'database_firewall_rules'
EXEC(@sql)
PRINT @sql
END
看来这个命令应该不带方巾
EXEC sp_msforeachtable 'drop table ?'
sp_msforeachtable在Azure SQL中不可用
对于Azure SQL:
此查询将删除外键约束
DECLARE @Name VARCHAR(200)
DECLARE @Constraint VARCHAR(300)
DECLARE @SQL VARCHAR(300)
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
这将从数据库中删除所有表
DECLARE @Name VARCHAR(200)
DECLARE @SQL VARCHAR(300)
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) +']' /*here you can change schema if it is different from dbo*/
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
你差不多说对了,可以用:
EXEC sp_msforeachtable 'ALTER TABLE ? NOCHECK CONSTRAINT all'
EXEC sp_msforeachtable 'DROP TABLE ?'
但是第二行你可能需要执行不止一次,直到你停止得到错误:
Could not drop object 'dbo.table' because it is referenced by a FOREIGN KEY constraint.
信息:
Command(s) completed successfully.
表示已成功删除所有表。
对于时态表来说,由于可能会有一些外键和例外,这有点复杂:
在表XXX上执行删除表操作失败,因为在系统版本的时态表上不支持该操作
你可以使用的是:
-- Disable constraints (foreign keys)
EXEC sp_MSForEachTable 'ALTER TABLE ? NOCHECK CONSTRAINT ALL'
GO
-- Disable system versioning (temporial tables)
EXEC sp_MSForEachTable '
IF OBJECTPROPERTY(object_id(''?''), ''TableTemporalType'') = 2
ALTER TABLE ? SET (SYSTEM_VERSIONING = OFF)
'
GO
-- Removing tables
EXEC sp_MSForEachTable 'DROP TABLE ?'
GO