如果 SQL Server 中存在外键约束,如何删除表?
Posted
技术标签:
【中文标题】如果 SQL Server 中存在外键约束,如何删除表?【英文标题】:How can I drop a table if there is a foreign key constraint in SQL Server? 【发布时间】:2013-02-27 08:23:31 【问题描述】:我有以下几点:
DROP TABLE [dbo].[ExtraUserInformation];
DROP TABLE [dbo].[UserProfile];
DROP TABLE [dbo].[webpages_Membership];
DROP TABLE [dbo].[webpages_OAuthMembership];
DROP TABLE [dbo].[webpages_Roles];
DROP TABLE [dbo].[webpages_UsersInRoles];
CREATE TABLE [dbo].[ExtraUserInformation] (
[Id] INT IDENTITY (1, 1) NOT NULL,
[UserId] INT NOT NULL,
[FullName] NVARCHAR (MAX) NULL,
[Link] NVARCHAR (MAX) NULL,
[Verified] BIT NULL,
CONSTRAINT [PK_dbo.ExtraUserInformation] PRIMARY KEY CLUSTERED ([Id] ASC)
);
CREATE TABLE [dbo].[webpages_UsersInRoles] (
[UserId] INT NOT NULL,
[RoleId] INT NOT NULL,
PRIMARY KEY CLUSTERED ([UserId] ASC, [RoleId] ASC),
CONSTRAINT [fk_UserId] FOREIGN KEY ([UserId]) REFERENCES [dbo].[UserProfile] ([UserId]),
CONSTRAINT [fk_RoleId] FOREIGN KEY ([RoleId]) REFERENCES [dbo].[webpages_Roles] ([RoleId])
);
但是这失败了,并显示一条消息:
Msg 3726, Level 16, State 1, Line 6
Could not drop object 'dbo.UserProfile' because it is referenced by a FOREIGN KEY constraint.
Msg 3726, Level 16, State 1, Line 9
Could not drop object 'dbo.webpages_Roles' because it is referenced by a FOREIGN KEY constraint.
Msg 2714, Level 16, State 6, Line 27
There is already an object named 'UserProfile' in the database.
Checking identity information: current identity value 'NULL', current column value 'NULL'.
DBCC execution completed. If DBCC printed error messages, contact your system administrator.
在这些情况下如何删除表?
【问题讨论】:
先删除引用 看看这个问题:***.com/questions/1776079/… 这是一个常见的 SQL Server 任务 你必须放弃约束 SQL DROP TABLE foreign key constraint的可能重复 【参考方案1】:您必须先删除约束,然后才能删除表。否则它的规则违规可能会破坏数据库的引用完整性。
如何获得外键关系请参阅这个老问题。 SQL DROP TABLE foreign key constraint
【讨论】:
【参考方案2】:1-首先,在删除表之后删除外键约束。
2-您可以通过执行以下查询来删除所有外键:
DECLARE @SQL varchar(4000)=''
SELECT @SQL =
@SQL + 'ALTER TABLE ' + s.name+'.'+t.name + ' DROP CONSTRAINT [' + RTRIM(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 s.schema_id = f.schema_id
--EXEC (@SQL)
PRINT @SQL
如果你执行打印的结果@SQL,外键将被丢弃。
【讨论】:
这会生成 所有 DROP CONSTRAINT 语句,而不仅仅是“我们”关心的语句。【参考方案3】:删除包含外部约束的表的最佳答案是:
步骤 1:删除表的主键。 第二步:现在会提示是否删除所有的外引用。 第 3 步:删除表。【讨论】:
谢谢,这对我有用。我想要的只是运行脚本来更新数据库中的用户表,并且为了测试,我只想将用户表从实时复制到开发副本......不必复制整个 5gb 数据库。【参考方案4】:您必须在删除表之前删除约束。
您可以使用这些查询来查找表中的所有 FK,并在使用您的表的表中查找 FK。
Declare @SchemaName VarChar(200) = 'Your Schema name'
Declare @TableName VarChar(200) = 'Your Table Name'
-- Find FK in This table.
SELECT
' IF EXISTS (SELECT * FROM sys.foreign_keys WHERE object_id =
OBJECT_ID(N''' +
'[' + OBJECT_SCHEMA_NAME(FK.parent_object_id) + '].[' + FK.name + ']'
+ ''') AND parent_object_id = OBJECT_ID(N''' +
'[' + OBJECT_SCHEMA_NAME(FK.parent_object_id) + '].[' +
OBJECT_NAME(FK.parent_object_id) + ']' + ''')) ' +
'ALTER TABLE ' + OBJECT_SCHEMA_NAME(FK.parent_object_id) +
'.[' + OBJECT_NAME(FK.parent_object_id) +
'] DROP CONSTRAINT ' + FK.name
, S.name , O.name, OBJECT_NAME(FK.parent_object_id)
FROM sys.foreign_keys AS FK
INNER JOIN Sys.objects As O
ON (O.object_id = FK.parent_object_id )
INNER JOIN SYS.schemas AS S
ON (O.schema_id = S.schema_id)
WHERE
O.name = @TableName
And S.name = @SchemaName
-- Find the FKs in the tables in which this table is used
SELECT
' IF EXISTS (SELECT * FROM sys.foreign_keys WHERE object_id =
OBJECT_ID(N''' +
'[' + OBJECT_SCHEMA_NAME(FK.parent_object_id) + '].[' + FK.name + ']'
+ ''') AND parent_object_id = OBJECT_ID(N''' +
'[' + OBJECT_SCHEMA_NAME(FK.parent_object_id) + '].[' +
OBJECT_NAME(FK.parent_object_id) + ']' + ''')) ' +
' ALTER TABLE ' + OBJECT_SCHEMA_NAME(FK.parent_object_id) +
'.[' + OBJECT_NAME(FK.parent_object_id) +
'] DROP CONSTRAINT ' + FK.name
, S.name , O.name, OBJECT_NAME(FK.parent_object_id)
FROM sys.foreign_keys AS FK
INNER JOIN Sys.objects As O
ON (O.object_id = FK.referenced_object_id )
INNER JOIN SYS.schemas AS S
ON (O.schema_id = S.schema_id)
WHERE
O.name = @TableName
And S.name = @SchemaName
【讨论】:
程序很好!! 这太疯狂了。我有一个表,它本身有一个外键约束(它自己的列引用另一个表)。当我发出删除表的命令时,SQL Server 真的应该在删除表之前删除该约束。深不可测,它无法处理。【参考方案5】: --Find and drop the constraints
DECLARE @dynamicSQL VARCHAR(MAX)
DECLARE MY_CURSOR CURSOR
LOCAL STATIC READ_ONLY FORWARD_ONLY
FOR
SELECT dynamicSQL = 'ALTER TABLE [' + OBJECT_SCHEMA_NAME(parent_object_id) + '].[' + OBJECT_NAME(parent_object_id) + '] DROP CONSTRAINT [' + name + ']'
FROM sys.foreign_keys
WHERE object_name(referenced_object_id) in ('table1', 'table2', 'table3')
OPEN MY_CURSOR
FETCH NEXT FROM MY_CURSOR INTO @dynamicSQL
WHILE @@FETCH_STATUS = 0
BEGIN
PRINT @dynamicSQL
EXEC (@dynamicSQL)
FETCH NEXT FROM MY_CURSOR INTO @dynamicSQL
END
CLOSE MY_CURSOR
DEALLOCATE MY_CURSOR
-- Drop tables
DROP 'table1'
DROP 'table2'
DROP 'table3'
【讨论】:
【参考方案6】:BhupeshC and murat ,这就是我要找的。但是 @SQL varchar(4000) 还不够大。所以,小改变
DECLARE @cmd varchar(4000)
DECLARE MY_CURSOR CURSOR
LOCAL STATIC READ_ONLY FORWARD_ONLY
FOR
select 'ALTER TABLE ['+s.name+'].['+t.name+'] DROP CONSTRAINT [' + RTRIM(f.name) +'];' FROM sys.Tables t INNER JOIN sys.foreign_keys f ON f.parent_object_id = t.object_id INNER JOIN sys.schemas s ON s.schema_id = f.schema_id
OPEN MY_CURSOR
FETCH NEXT FROM MY_CURSOR INTO @cmd
WHILE @@FETCH_STATUS = 0
BEGIN
-- EXEC (@cmd)
PRINT @cmd
FETCH NEXT FROM MY_CURSOR INTO @cmd
END
CLOSE MY_CURSOR
DEALLOCATE MY_CURSOR
GO
【讨论】:
【参考方案7】:如果 mysql 服务器中存在外键约束,则删除表?
运行sql查询:
SET FOREIGN_KEY_CHECKS = 0; DROP TABLE 表名
希望对你有帮助!
【讨论】:
问题是关于 Microsoft SQL Server 而不是 MySQL 虽然这个问题是关于 SQL Server 的,但我想在 MySQL 中做同样的事情,这个答案对我有帮助。【参考方案8】:重新删除约束并删除表,此脚本可以获取选定表列表的所有约束,然后删除约束,然后删除表。
DECLARE @id INT
DECLARE @strSQL NVARCHAR(max)
DECLARE @deleteCurser CURSOR
DECLARE @deleteTableCurser CURSOR
declare @SelectedTables table ([name] sysname, [object_id] int)
Insert into @SelectedTables ([name], [object_id])
SELECT t.name, t.object_id
FROM sys.Tables t
where t.name in
-- Change Name of tables here
('table1','table2','table100')
SET @deleteTableCurser = CURSOR FOR
SELECT strSQL =
'ALTER TABLE ' + s.name+'.'+t.name + ' DROP CONSTRAINT [' + RTRIM(f.name) +'];'
FROM @SelectedTables t
INNER JOIN sys.foreign_keys f ON f.parent_object_id = t.object_id
INNER JOIN sys.schemas s ON s.schema_id = f.schema_id
OPEN @deleteTableCurser
FETCH Next
FROM @deleteTableCurser INTO @strSQL
WHILE @@FETCH_STATUS = 0
BEGIN
print(@strSQL)
EXEC (@strSQL)
FETCH NEXT
FROM @deleteTableCurser INTO @strSQL
END
CLOSE @deleteTableCurser
DEALLOCATE @deleteTableCurser
SET @deleteCurser = CURSOR FOR
SELECT strSQL = 'DROP TABLE ['+ t.name+ '];'
FROM @SelectedTables t
OPEN @deleteCurser
FETCH Next
FROM @deleteCurser INTO @strSQL
WHILE @@FETCH_STATUS = 0
BEGIN
print(@strSQL)
EXEC (@strSQL)
FETCH NEXT
FROM @deleteCurser INTO @strSQL
END
CLOSE @deleteCurser
DEALLOCATE @deleteCurser
【讨论】:
【参考方案9】:输入这个....SET foreign_key_checks = 0;
删除你的表然后输入SET foreign_key_checks = 1;
MySQL – Temporarily disable Foreign Key Checks or Constraints
【讨论】:
以上是关于如果 SQL Server 中存在外键约束,如何删除表?的主要内容,如果未能解决你的问题,请参考以下文章