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 AIDmytableを想定していますか?
Mike Purcell、

回答:


228

外部キーを削除する必要があります。MySQLの外部キーは自動的にテーブルにインデックスを作成します(このトピックについてのSOの質問がありました)。

ALTER TABLE mytable DROP FOREIGN KEY mytable_ibfk_1 ; 

12
インデックスを削除した後で再度追加することもできますmytable。ALTERTABLE ADD CONSTRAINT mytable_ibfk_1FOREIGN KEY(AID)REFERENCES mytable_aID)ON DELETE CASCADE;
laffuste 2014

8
それはすばらしいことですが、FOREIGN KEY制約が匿名であった場合はどうすればよいですか?
Pehat

下に私の答えをチェックし@Pehat stackoverflow.com/a/54145440/2305119
thyzz

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>

ステップ3

インデックスを削除します。


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 ;

エラーが発生します。


インデックスを削除して、1つの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

外部キーには常にインデックスが必要です。インデックスを使用せずに制約を適用すると、参照テーブルに挿入または更新されたキーごとに、参照テーブルで全テーブルスキャンが必要になります。そして、それは許容できないパフォーマンスの影響を与えるでしょう。これには次の2つの影響があります。

  • 外部キーを作成するとき、データベースはインデックスが存在するかどうかをチェックします。そうでない場合、インデックスが作成されます。デフォルトでは、制約と同じ名前になります。
  • 外部キーに使用できるインデックスが1つしかない場合、それを削除することはできません。本当に削除したくない場合は、最初に外部キー制約を削除するか、または別のインデックスを作成する必要があります。

1
あなたは他の答えが欠けていたという理論を持っています。
デニス

1
したがって:複合一意インデックス(一意制約の複数の列)がある場合、AとBのインデックスがない限り、一意のABキーを削除できません。このエラーが発生する場合、別のテーブルが列AまたはB、そしてABを安全に削除する前にそれらを追加する必要があります。
Robin De Schepper

@RobinDeSchepper良い発言。また、複合一意インデックスを使用する場合、フィールドの順序は一意インデックスにとって重要ではありませんが、外部キーにとっては重要な場合があります。A、B上の一意のインデックスは、A上の外部キーによってではなく、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

0

私の場合、外部キーを削除しましたが、それでもインデックスを削除できませんでした。これは、同じフィールドにこのテーブルへの外部キーを持つ別のテーブルがあったためです。他のテーブルの外部キーを削除した後、このテーブルのインデックスを削除できました。


0

外部キー列をドロップする場合(魔女が制約を保持)、最初に外部キーをドロップしてから列をドロップする必要があります。外部キーをドロップするとき、すべての名前を渡す必要はなく、単に外部キーを渡します。列名:

$table->dropForeign(['currency_id']);
$table->dropColumn('currency_id');

詳細:

https://laravel.com/docs/6.x/migrations#foreign-key-constraints

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.