如果 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 中存在外键约束,如何删除表?的主要内容,如果未能解决你的问题,请参考以下文章

ORACLE语句怎么删除外键约束,只是删约束,不是删表

[SQL] SQL SERVER基础语法

[SQL] SQL SERVER基础语法

sql server如何添加外键

sql server如何添加外键

sqlserver外键关系有啥用?