如果我想像这样删除数据库中的所有表,它会处理外键约束吗?如果没有,我该如何处理?
GO
IF OBJECT_ID('dbo.[Course]','U') IS NOT NULL
DROP TABLE dbo.[Course]
GO
IF OBJECT_ID('dbo.[Student]','U') IS NOT NULL
DROP TABLE dbo.[Student]
不,如果确实有外键引用它,这不会删除您的表。
要获取引用您的表的所有外键关系,您可以使用此 SQL(如果您使用的是 SQL Server 2005 及更高版本):
SELECT *
FROM sys.foreign_keys
WHERE referenced_object_id = object_id('Student')
如果有的话,使用这里的语句,您可以创建 SQL 语句来实际删除这些 FK 关系:
SELECT
'ALTER TABLE [' + OBJECT_SCHEMA_NAME(parent_object_id) +
'].[' + OBJECT_NAME(parent_object_id) +
'] DROP CONSTRAINT [' + name + ']'
FROM sys.foreign_keys
WHERE referenced_object_id = object_id('Student')
在 SQL Server Management Studio 2008 (R2) 及更高版本中,您可以右键单击
数据库 -> 任务 -> 生成脚本
选择您要删除的表。
选择“保存到新查询窗口”。
单击“高级”按钮。
将 Script DROP 和 CREATE 设置为 Script DROP。
将脚本外键设置为 True。
单击“确定”。
单击“下一步”->“下一步”->“完成”。
查看脚本然后执行。
如果您先删除“子”表,则外键也会被删除。如果您尝试先删除“父”表,您将收到“无法删除对象 'a',因为它被外键约束引用”。错误。
这是正确删除所有表的另一种方法,使用
sp_MSdropconstraints
过程。我能想到的最短的代码:
exec sp_MSforeachtable "declare @name nvarchar(max); set @name = parsename('?', 1); exec sp_MSdropconstraints @name";
exec sp_MSforeachtable "drop table ?";
@mark_s 发布的内容稍微更通用,这对我有帮助
SELECT
'ALTER TABLE ' + OBJECT_SCHEMA_NAME(k.parent_object_id) +
'.[' + OBJECT_NAME(k.parent_object_id) +
'] DROP CONSTRAINT ' + k.name
FROM sys.foreign_keys k
WHERE referenced_object_id = object_id('your table')
只需插入你的表名,然后执行它的结果。
一切都变得简单多了。有一个配置可以关闭检查然后打开。
例如,如果您正在使用MySQL,那么要关闭它,您必须编写
SET foreign_key_checks = 0;
然后删除或清除表格,并重新启用检查
SET foreign_key_checks = 1;
如果是 SQL Server,则必须先删除约束,然后才能删除表。
这是删除表本身后面的所有约束的另一种方法,使用涉及
FOR XML PATH('')
的串联技巧,它允许将多个输入行合并到单个输出行中。应该适用于任何 SQL 2005 及更高版本。
为了安全起见,我已将 EXECUTE 命令注释掉。
DECLARE @SQL NVARCHAR(max)
;WITH fkeys AS (
SELECT quotename(s.name) + '.' + quotename(o.name) tablename, quotename(fk.name) constraintname
FROM sys.foreign_keys fk
JOIN sys.objects o ON fk.parent_object_id = o.object_id
JOIN sys.schemas s ON o.schema_id = s.schema_id
)
SELECT @SQL = STUFF((SELECT '; ALTER TABLE ' + tablename + ' DROP CONSTRAINT ' + constraintname
FROM fkeys
FOR XML PATH('')),1,2,'')
-- EXECUTE(@sql)
SELECT @SQL = STUFF((SELECT '; DROP TABLE ' + quotename(TABLE_SCHEMA) + '.' + quotename(TABLE_NAME)
FROM INFORMATION_SCHEMA.TABLES
FOR XML PATH('')),1,2,'')
-- EXECUTE(@sql)
这是实现解决方案的完整脚本:
create Procedure [dev].DeleteTablesFromSchema
(
@schemaName varchar(500)
)
As
begin
declare @constraintSchemaName nvarchar(128), @constraintTableName nvarchar(128), @constraintName nvarchar(128)
declare @sql nvarchar(max)
-- delete FK first
declare cur1 cursor for
select distinct
CASE WHEN t2.[object_id] is NOT NULL THEN s2.name ELSE s.name END as SchemaName,
CASE WHEN t2.[object_id] is NOT NULL THEN t2.name ELSE t.name END as TableName,
CASE WHEN t2.[object_id] is NOT NULL THEN OBJECT_NAME(d2.constraint_object_id) ELSE OBJECT_NAME(d.constraint_object_id) END as ConstraintName
from sys.objects t
inner join sys.schemas s
on t.[schema_id] = s.[schema_id]
left join sys.foreign_key_columns d
on d.parent_object_id = t.[object_id]
left join sys.foreign_key_columns d2
on d2.referenced_object_id = t.[object_id]
inner join sys.objects t2
on d2.parent_object_id = t2.[object_id]
inner join sys.schemas s2
on t2.[schema_id] = s2.[schema_id]
WHERE t.[type]='U'
AND t2.[type]='U'
AND t.is_ms_shipped = 0
AND t2.is_ms_shipped = 0
AND s.Name=@schemaName
open cur1
fetch next from cur1 into @constraintSchemaName, @constraintTableName, @constraintName
while @@fetch_status = 0
BEGIN
set @sql ='ALTER TABLE ' + @constraintSchemaName + '.' + @constraintTableName+' DROP CONSTRAINT '+@constraintName+';'
exec(@sql)
fetch next from cur1 into @constraintSchemaName, @constraintTableName, @constraintName
END
close cur1
deallocate cur1
DECLARE @tableName nvarchar(128)
declare cur2 cursor for
select s.Name, p.Name
from sys.objects p
INNER JOIN sys.schemas s ON p.[schema_id] = s.[schema_id]
WHERE p.[type]='U' and is_ms_shipped = 0
AND s.Name=@schemaName
ORDER BY s.Name, p.Name
open cur2
fetch next from cur2 into @schemaName,@tableName
while @@fetch_status = 0
begin
set @sql ='DROP TABLE ' + @schemaName + '.' + @tableName
exec(@sql)
fetch next from cur2 into @schemaName,@tableName
end
close cur2
deallocate cur2
end
go
Removing Referenced FOREIGN KEY Constraints
Assuming there is a parent and child table Relationship in SQL Server:
--First find the name of the Foreign Key Constraint:
SELECT *
FROM sys.foreign_keys
WHERE referenced_object_id = object_id('States')
--Then Find foreign keys referencing to dbo.Parent(States) table:
SELECT name AS 'Foreign Key Constraint Name',
OBJECT_SCHEMA_NAME(parent_object_id) + '.' + OBJECT_NAME(parent_object_id) AS 'Child Table'
FROM sys.foreign_keys
WHERE OBJECT_SCHEMA_NAME(referenced_object_id) = 'dbo' AND
OBJECT_NAME(referenced_object_id) = 'dbo.State'
-- Drop the foreign key constraint by its name
ALTER TABLE dbo.cities DROP CONSTRAINT FK__cities__state__6442E2C9;
-- You can also use the following T-SQL script to automatically find
--and drop all foreign key constraints referencing to the specified parent
-- table:
BEGIN
DECLARE @stmt VARCHAR(300);
-- Cursor to generate ALTER TABLE DROP CONSTRAINT statements
DECLARE cur CURSOR FOR
SELECT 'ALTER TABLE ' + OBJECT_SCHEMA_NAME(parent_object_id) + '.' +
OBJECT_NAME(parent_object_id) +
' DROP CONSTRAINT ' + name
FROM sys.foreign_keys
WHERE OBJECT_SCHEMA_NAME(referenced_object_id) = 'dbo' AND
OBJECT_NAME(referenced_object_id) = 'states';
OPEN cur;
FETCH cur INTO @stmt;
-- Drop each found foreign key constraint
WHILE @@FETCH_STATUS = 0
BEGIN
EXEC (@stmt);
FETCH cur INTO @stmt;
END
CLOSE cur;
DEALLOCATE cur;
END
GO
--Now you can drop the parent table:
DROP TABLE states;
--# Command(s) completed successfully.
使用 SQL Server Manager,您可以从 UI 中删除外键约束。如果要删除表
Diary
但 User 表有一个外键 DiaryId
指向 Diary
表,您可以展开(使用加号)User
表,然后展开 Foreign Keys
部分。右键单击指向日记表的外键,然后选择 Delete
。然后,您可以展开 Columns
部分,右键单击并删除 DiaryId
列。然后你就可以运行:
drop table Diary
我知道您的实际问题是关于删除所有表,因此这对于这种情况可能没有用。但是,如果您只想删除一些表,我相信这是有用的(标题没有明确提到删除所有表)。
执行以下代码以获取阻止您删除的外键约束名称。例如,我采用
roles
表。
SELECT *
FROM sys.foreign_keys
WHERE referenced_object_id = object_id('roles');
SELECT name AS 'Foreign Key Constraint Name',
OBJECT_SCHEMA_NAME(parent_object_id) + '.' + OBJECT_NAME(parent_object_id)
AS 'Child Table' FROM sys.foreign_keys
WHERE OBJECT_SCHEMA_NAME(referenced_object_id) = 'dbo'
AND OBJECT_NAME(referenced_object_id) = 'dbo.roles'
您将获得如下 FK 名称:
FK__Table1__roleId__1X1H55C1
现在运行以下代码以删除从上面获得的 FK 引用。
ALTER TABLE dbo.users drop CONSTRAINT FK__Table1__roleId__1X1H55C1;
完成!
如果您使用的是 mysql 服务器(不是 MSSQL)并且您不介意丢失表,则可以使用简单的查询一次删除多个表:
SET foreign_key_checks = 0;
DROP TABLE IF EXISTS table_a,table_b,table_c,table_etc;
SET foreign_key_checks = 1;
通过这种方式,在查询中使用表的顺序并不重要。
如果有人要说,如果您有一个包含许多表的数据库,这不是一个好的解决方案:我同意!
找到所有外键..编写它们的脚本
SELECT * FROM sys.foreign_keys
WHERE referenced_object_id = object_id('Student')
然后从子表中删除外键。 现在你可以删除父表了。
如果您想重新创建父表,请确保运行您之前创建的脚本。
此脚本将允许您使用约束名称上的字符串匹配来删除所有外键约束
DECLARE @constraintMatchString nvarchar(max) = N'FK_<SOME-MATCH-STRING>%';
DECLARE @sql nvarchar(max) = N'';
;WITH x (schemaAndTableName, constraintName) AS
(
SELECT
schemaAndTableName = QUOTENAME(OBJECT_SCHEMA_NAME(parent_object_id)) + '.' + QUOTENAME(OBJECT_NAME(parent_object_id)),
constraintName = name
FROM sys.foreign_keys
where name like @constraintMatchString
group by QUOTENAME(OBJECT_SCHEMA_NAME(parent_object_id)) + '.' + QUOTENAME(OBJECT_NAME(parent_object_id)), name
)
SELECT @sql += N'ALTER TABLE ' + schemaAndTableName + N' DROP CONSTRAINT [' +constraintName +N'];
' FROM x;
EXEC sys.sp_executesql @sql;
只需根据需要替换
FK_<SOME-MATCH-STRING>%
值(请注意,%
是通配符匹配)
如果您想要
DROP
已被其他表使用外键引用的表,请使用DROP TABLE *table_name* CASCADE CONSTRAINTS;
如果我想删除里面所有的表 我的数据库
然后删除整个数据库就容易多了:
DROP DATABASE WorkerPensions