MySQL无法删除外键约束中所需的索引


155

我需要更改现有数据库以添加列。因此,我也想更新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上?
Mike Purcell

Answers:


228

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

ALTER TABLE mytable DROP FOREIGN KEY mytable_ibfk_1 ; 

12
您可能希望在删除索引后重新添加它:删除级联时ALTER TABLE mytableADD CONSTRAINT mytable_ibfk_1FOREIGN KEY(AID)参考mytable_aID);
laffuste 2014年

8
很好,但是如果我的FOREIGN KEY约束是匿名的怎么办?
Pehat '16


1
注意:外键可能不太明显。要查找与表和列相关的所有外键,可以使用以下查询:dba.stackexchange.com/questions/102371/…–
charlax

84

第1步

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

SHOW CREATE TABLE  <Table Name>

结果将显示您的外键名称。

格式:

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

第2步

放下(外国/主要/钥匙)钥匙

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

第三步

删除索引。


18

如果您表示可以这样做:

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);

8

因为您必须在外键字段上具有索引,所以只需在字段“ AID”上创建一个简单的索引

CREATE INDEX aid_index ON mytable (AID);

然后删除唯一索引“ AID”

ALTER TABLE mytable DROP INDEX AID;

7

外键始终需要索引。如果没有索引,则约束将要求对引用表中的每个插入或更新的键对引用表进行全表扫描。这会对性能造成不可接受的影响。这具有以下两个后果:

  • 创建外键时,数据库将检查索引是否存在。如果不是,将创建索引。默认情况下,它将与约束具有相同的名称。
  • 如果只有一个索引可用于外键,则不能将其删除。如果您确实不想删除它,则必须删除外键约束或首先为其创建另一个索引。

1
您有其他答案缺乏的理论。
丹尼斯,

1
因此:如果您具有复合唯一索引(在唯一约束中有多个列),则除非您具有A和B的索引,否则无法删除唯一AB键。如果出现此错误,则另一个表正在使用A列或B列的索引B,并且您必须先添加它们,然后才能安全删除唯一的AB。
罗宾·德·史珀

@RobinDeSchepper好的评论。并且,当使用复合唯一索引时,字段的顺序对于唯一索引并不重要,但对于外键可能很重要。上一个唯一索引,B可以通过在一个外键使用,但不能由B的外键
斯特凡Mondelaers

2

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

set FOREIGN_KEY_CHECKS=1;

ALTER TABLE mytable DROP INDEX AID;

set FOREIGN_KEY_CHECKS=0;

2
我认为您交换了启用和禁用支票。在我期望FOREIGN_KEY_CHEK=0的最高端,最后FOREIGN_KEY_CHEK=1
romor

0

就我而言,我删除了外键,但仍然无法删除索引。那是因为在同一字段上还有另一个表对此表具有外键。将外键放在另一个表上之后,可以在该表上删除索引。


By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.