【问题标题】:MySQL Cannot drop index needed in a foreign key constraintMySQL 无法删除外键约束中所需的索引
【发布时间】:2012-01-18 22:06:12
【问题描述】:

我需要更改我现有的数据库以添加一列。因此,我还想更新 UNIQUE 字段以包含该新列。我正在尝试删除当前索引,但不断收到错误 MySQL Cannot drop index needed in a foreign key constraint

CREATE TABLE mytable_a (
ID          TINYINT NOT NULL AUTO_INCREMENT PRIMARY KEY,
Name        VARCHAR(255) NOT NULL,
UNIQUE(Name)
) ENGINE=InnoDB;

CREATE TABLE mytable_b (
ID          TINYINT NOT NULL AUTO_INCREMENT PRIMARY KEY,
Name        VARCHAR(255) NOT NULL,
UNIQUE(Name)
) ENGINE=InnoDB;

CREATE TABLE mytable_c (
ID          TINYINT NOT NULL AUTO_INCREMENT PRIMARY KEY,
Name        VARCHAR(255) NOT NULL,
UNIQUE(Name)
) ENGINE=InnoDB;


CREATE TABLE `mytable` (
  `ID` int(11) NOT NULL AUTO_INCREMENT,
  `AID` tinyint(5) NOT NULL,
  `BID` tinyint(5) NOT NULL,
  `CID` tinyint(5) NOT NULL,
  PRIMARY KEY (`ID`),
  UNIQUE KEY `AID` (`AID`,`BID`,`CID`),
  KEY `BID` (`BID`),
  KEY `CID` (`CID`),
  CONSTRAINT `mytable_ibfk_1` FOREIGN KEY (`AID`) REFERENCES `mytable_a` (`ID`) ON DELETE CASCADE,
  CONSTRAINT `mytable_ibfk_2` FOREIGN KEY (`BID`) REFERENCES `mytable_b` (`ID`) ON DELETE CASCADE,
  CONSTRAINT `mytable_ibfk_3` FOREIGN KEY (`CID`) REFERENCES `mytable_c` (`ID`) ON DELETE CASCADE
) ENGINE=InnoDB;




mysql> ALTER TABLE mytable DROP INDEX AID;
ERROR 1553 (HY000): Cannot drop index 'AID': needed in a foreign key constraint

【问题讨论】:

  • 假设 UNIQUE KEY AID 在 mytable 上?

标签: mysql


【解决方案1】:

您必须删除外键。 MySQL 中的外键自动在表上创建索引(主题上有一个SO Question)。

ALTER TABLE mytable DROP FOREIGN KEY mytable_ibfk_1 ; 

【讨论】:

  • 您可能希望在删除索引后将其添加回来: ALTER TABLE mytable ADD CONSTRAINT mytable_ibfk_1 FOREIGN KEY (AID) REFERENCES mytable_a (ID) ON DELETE CASCADE;
  • 很好,但是如果我的 FOREIGN KEY 约束是匿名的,我该怎么办?
  • @Pehat 在下面查看我的答案stackoverflow.com/a/54145440/2305119
  • 注意:外键可能不那么明显。要查找与表和列相关的所有外键,可以使用以下查询:dba.stackexchange.com/questions/102371/…
  • 我讨厌这是正确的答案,但确实如此。 (赞成)。是的,正如 Iaffuste 所说,您可能希望在删除索引(或约束)后重新添加 FK。
【解决方案2】:

如果你的意思是你可以这样做:

CREATE TABLE mytable_d (
ID          TINYINT NOT NULL AUTO_INCREMENT PRIMARY KEY,
Name        VARCHAR(255) NOT NULL,
UNIQUE(Name)
) ENGINE=InnoDB;


ALTER TABLE mytable
ADD COLUMN DID tinyint(5) NOT NULL,
ADD CONSTRAINT mytable_ibfk_4 
      FOREIGN KEY (DID) 
        REFERENCES mytable_d (ID) ON DELETE CASCADE;

 > OK.

然后:

ALTER TABLE mytable
DROP KEY AID ;

给出错误。


您可以删除索引并在ALTER TABLE 语句中创建一个新的:

ALTER TABLE mytable
DROP KEY AID ,
ADD UNIQUE KEY AID (AID, BID, CID, DID);

【讨论】:

    【解决方案3】:

    步骤 1

    列出外键(注意它与索引名称不同)

    SHOW CREATE TABLE  <Table Name>
    

    结果会显示外键名。

    格式:

    CONSTRAINT `FOREIGN_KEY_NAME` FOREIGN KEY (`FOREIGN_KEY_COLUMN`) REFERENCES `FOREIGN_KEY_TABLE` (`id`),
    

    第二步

    删除(外/主/键)键

    ALTER TABLE <Table Name> DROP FOREIGN KEY <Foreign key name>
    

    第三步

    删除索引。

    【讨论】:

      【解决方案4】:

      因为你必须在外键字段上有一个索引,所以你可以在字段“AID”​​上创建一个简单的索引

      CREATE INDEX aid_index ON mytable (AID);
      

      然后才删除唯一索引“AID”​​

      ALTER TABLE mytable DROP INDEX AID;
      

      【讨论】:

        【解决方案5】:

        我认为这是删除索引的简单方法。

        set FOREIGN_KEY_CHECKS=0; //disable checks
        
        ALTER TABLE mytable DROP INDEX AID;
        
        set FOREIGN_KEY_CHECKS=1; //enable checks
        

        【讨论】:

        • 我认为您交换了启用和禁用检查。在顶部,我期望FOREIGN_KEY_CHEK=0,最后是FOREIGN_KEY_CHEK=1
        • 我编辑了答案,打开了关闭检查并添加了 cmets。如果可以的话,我会投票给这个服务器时间:D 谢谢你,拉姆。
        • 投了反对票,因为这不起作用。我仍然无法删除唯一索引。
        • 这真的行不通。我将不得不先删除外键。
        【解决方案6】:

        外键总是需要索引。如果没有执行约束的索引,则需要对引用表中的每个插入或更新的键进行全表扫描。这将产生不可接受的性能影响。 这有以下两个后果:

        • 创建外键时,数据库会检查索引是否存在。如果没有,将创建索引。默认情况下,它将与约束具有相同的名称。
        • 当只有一个索引可以用于外键时,它不能被删除。如果你真的不想删除它,你要么必须删除外键约束,要么先为其创建另一个索引。

        【讨论】:

        • 你有其他答案所缺乏的理论。
        • 所以:如果你有一个复合唯一索引(一个唯一约束中的多个列)你不能删除唯一的 AB 键,除非你有 A 和 B 的索引。如果你得到这个错误,另一个表正在使用 A 列或 B 列的索引,您必须先添加这些索引,然后才能安全地删除 AB 唯一。
        • @RobinDeSchepper 好话。并且在使用复合唯一索引时,字段的顺序对于唯一索引并不重要,但对于外键可能很重要。 A,B 上的唯一索引可以被 A 上的外键使用,但不能被 B 上的外键使用。
        【解决方案7】:

        在我的情况下,我删除了外键,但仍然无法删除索引。那是因为还有另一个表在同一字段上具有该表的外键。在我删除另一个表上的外键后,我可以删除这个表上的索引。

        【讨论】:

          【解决方案8】:

          如果您使用的是 PhpMyAdmin,有时它不会显示要删除的外键。

          错误代码给了我们外键的名称和定义它的表,所以代码是:

          ALTER TABLE your_table DROP FOREIGN KEY foreign_key_name; 
          

          【讨论】:

            【解决方案9】:

            在同一个查询中删除索引和外键,如下所示

            ALTER TABLE `your_table_name` DROP FOREIGN KEY `your_index`;
            ALTER TABLE `your_table_name` DROP COLUMN `your_foreign_key_id`;
            

            【讨论】:

              【解决方案10】:

              您可以在 phpMyAdmin 中显示关系视图并首先删除外键。在此之后,您可以删除索引。

              【讨论】:

                【解决方案11】:

                您可以使用 DBeaver 轻松检查它。例子:

                如您所见,有 3 个 FK,但只有 2 个 FK 索引。 FK_benefCompanyNumber_beneficiaries_benefId 没有索引,因为英国索引为该 FK 提供了唯一性。

                要放弃英国,您需要:

                1. DROP FK_benefCompanyNumber_beneficiaries_benefId
                2. 放弃英国
                3. 创建 FK_benefCompanyNumber_beneficiaries_benefId

                【讨论】:

                  猜你喜欢
                  • 2022-08-14
                  • 2014-09-07
                  • 1970-01-01
                  • 2021-05-13
                  • 2014-10-26
                  • 1970-01-01
                  • 1970-01-01
                  • 1970-01-01
                  • 2011-12-29
                  相关资源
                  最近更新 更多