MySQLの外部キー制約を追加する際にエラー。
「ERROR 1215 (HY000): Cannot add foreign key constraint」とな。
実際はどうにも初歩的なミスなのですが、MySQL関連は忘れがちなので備忘録。
外部キー設定でエラーが発生した時は、「SHOW ENGINE INNODB STATUS」コマンドの”LATEST FOREIGN KEY ERROR”の項目にエラー内容が記載されています。
その辺で確認しながら、エラーを解消。
MySQLの外部キー制約時のエラーはSHOW ENGINE INNODB STATUSで確認
ALTER TABLE bar ADD FOREIGN KEY (foo_code) REFERENCES foo (code) ON DELETE RESTRICT ON UPDATE RESTRICT;
こんな感じで外部キー制約を追加しようとした時のこと。
ERROR 1215 (HY000): Cannot add foreign key constraint
なんつって怒られました。
外部キー制約設定時のエラーは、下記の文で詳細なエラー内容が確認できます。
SHOW ENGINE INNODB STATUS\G
この一文すぐ忘れるちゃうんですよね。
出力された内容の中の”LATEST FOREIGN KEY ERROR”の項目にエラー内容が書かれています。
「ERROR 1215 (HY000): Cannot add foreign key constraint」の正体
“LATEST FOREIGN KEY ERROR”の内容は下記のようなものでした。
————————
LATEST FOREIGN KEY ERROR
————————
2019-08-08 13:46:39 0x7000019ab000 Error in foreign key constraint of table foo/#sql-1126_c4:
FOREIGN KEY (foo_code) REFERENCES foo (code) :
Cannot find an index in the referenced table where the
referenced columns appear as the first columns, or column types
in the table and the referenced table do not match for constraint.
Note that the internal storage type of ENUM and SET changed in
tables created with >= InnoDB-4.1.12, and such columns in old tables
cannot be referenced by such columns in new tables.
Please refer to http://dev.mysql.com/doc/refman/5.7/en/innodb-foreign-key-constraints.html for correct foreign key definition.
さて、ここでテーブル設計を改めて見直し……。
CREATE TABLE foo ( id INTEGER PRIMARY KEY AUTO_INCREMENT, code INTEGER NOT NULL, name VARCHAR(64) NOT NULL, created_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP, updated_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP ) ENGINE = InnoDB DEFAULT CHARACTER SET 'utf8'; CREATE TABLE bar ( id INTEGER PRIMARY KEY AUTO_INCREMENT, foo_code INTEGER NOT NULL, created_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP, updated_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP ) ENGINE = InnoDB DEFAULT CHARACTER SET 'utf8'; ALTER TABLE bar ADD FOREIGN KEY (foo_code) REFERENCES foo (code) ON DELETE RESTRICT ON UPDATE RESTRICT;
見直したらすぐに気付いたわけですが、「参照される側のテーブルの項目はPRIMARY KEYでなくてはならない」ってやつですね。
fooテーブルの”code”がPRIMARY KEYじゃないからってイージーミスでした。
“code”をPRIMARY KEYにして設定しようとすると、別エラーで外部キー制約設定できず……。
SET FOREIGN_KEY_CHECKS=0;
で、一時的に外部キー制約を無効にして設定し直したら無事設定完了。ホッ。
コメント