【问题标题】:Could not drop object 'dbo.Table1' because it is referenced by a FOREIGN KEY constraint无法删除对象“dbo.Table1”,因为它被 FOREIGN KEY 约束引用
【发布时间】:2014-10-05 17:07:01
【问题描述】:

即使我正在删除并尝试删除表,我也会收到错误,

ALTER TABLE [dbo].[Table1] DROP CONSTRAINT [FK_Table1_Table2]
GO

DROP TABLE [dbo].[Table1]
GO

错误

消息 3726,级别 16,状态 1,行 2 无法删除对象 'dbo.Table1' 因为它被 FOREIGN KEY 约束引用。

使用 SQL Server 2012

我使用 sql server 2012 生成了脚本,那么 sql server 是否给了我错误的脚本?

【问题讨论】:

  • 这是一个令人沮丧的过程,因为您无疑正在经历。试试这个:我在构建表时保持一个“依赖项”电子表格,其中记录了每个表创建的 PK 以及它在其他表中引用的 FK。当您确定用户如何添加数据时,无论如何您都需要此信息。例如,当用户在屏幕上并向 Table1 添加记录时,需要向 Table2 和 Table3 添加什么之前才能追加到 Table1?这些规则可以通过验证或向用户发出警告来强制执行。希望这会有所帮助。

标签: sql sql-server


【解决方案1】:

发生这种情况是因为您尝试更改的表有一个主键 (PK),该主键 (PK) 在不同表的某处被引用为外键 (FK)。要知道它是哪个表,请执行以下存储过程:

EXEC sp_fkeys 'Table_Name'

然后运行drop命令,如下:

DROP TABLE Table_Name

注意: 'dbo.'是默认的系统派生架构,因此您不必在命令中提及,如下所示。即使您提及架构,它也会起作用。

DROP TABLE dbo.Table_Name

【讨论】:

    【解决方案2】:

    您可以使用这些查询来查找表中的所有 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 
    

    【讨论】:

      【解决方案3】:

      您需要将 FK 放在它已添加到的表上,现在这可以是 Table2、Table3 或任何将 Table1 的列作为外键引用的表。然后你可以删除 Table1。

      【讨论】:

      • 为了删除一个表,您必须删除存在于指向您要删除的表的其他表上的 FK。 Management Studio 不会自动将其作为 DROP 脚本的一部分生成。我没有说 FK_Table1_Table2 属于表 1,我说你需要删除表 2 上的 FK(不管它叫什么)。您可以通过右键单击表并查看“依赖项”来找到所有引用表 1 的 FK。
      【解决方案4】:

      不确定我是否正确理解了您要执行的操作,很可能 Table1 在另一个表中被引用为 FK。

      如果你这样做:

      EXEC sp_fkeys 'Table1'
      

      (取自How can I list all foreign keys referencing a given table in SQL Server?

      这将为您提供“Table1”主键为 FK 的所有表。

      删除表中存在的约束不是删除表本身的必要步骤。删除所有可能引用“Table1”的 FK。

      关于你问题的第二部分,SQL Server 自动脚本在很多方面都是盲目的。最有可能阻止您删除 Table1 的表被删除或根本不被脚本更改。 RedGate 有一些工具可以帮助进行级联删除(通常是在您尝试删除一堆表时),但它不是防弹的,而且价格相当昂贵。 http://www.red-gate.com/products/sql-development/sql-toolbelt/

      【讨论】:

        【解决方案5】:

        首先,您需要放下 FK。

        我可以推荐你看看这个堆栈溢出帖子,非常有趣。它被称为:SQL DROP TABLE foreign key constraint

        关于如何执行此过程有一个很好的解释。

        我会引用一个回应:

        .....如果确实有外键引用它,则不会删除您的表。

        要获取引用您的表的所有外键关系,您可以使用此 SQL(如果您使用的是 SQL Server 2005 及更高版本):

        SELECT * 
        FROM sys.foreign_keys
        WHERE referenced_object_id = object_id('Student')
        
        
        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')
        

        【讨论】:

          猜你喜欢
          • 2010-09-20
          • 1970-01-01
          • 2016-11-04
          • 2014-03-20
          • 2021-05-30
          • 2019-10-05
          • 2016-11-29
          • 2015-04-29
          • 2020-01-05
          相关资源
          最近更新 更多