※この記事にはアフィリエイト広告(プロモーション)が含まれます。
外部キーで親子関係を付けた表では、親に無い値を子に入れようとすると ERROR 1452、子から参照されている親を消そうとすると ERROR 1451 になります。
ERROR 1452 (23000): Cannot add or update a child row: a foreign key constraint fails (`fkdb`.`child`, CONSTRAINT `child_ibfk_1` FOREIGN KEY (`parent_id`) REFERENCES `parent` (`id`))
ERROR 1451 (23000): Cannot delete or update a parent row: a foreign key constraint fails (`fkdb`.`child`, CONSTRAINT `child_ibfk_1` FOREIGN KEY (`parent_id`) REFERENCES `parent` (`id`))
この記事のログは MySQL 8.4.11(Ubuntu 26.04 の標準パッケージ)で採りました。表は次のとおりです。
CREATE TABLE parent (id int PRIMARY KEY, name varchar(20));
CREATE TABLE child (id int PRIMARY KEY, parent_id int,
FOREIGN KEY (parent_id) REFERENCES parent(id));
まず見る(結論)
括弧の中に、子の表・制約名・子の列・親の表と列が全部出ています。
| エラー | 操作 | 対処 |
|---|---|---|
| 1452 | 子への INSERT / UPDATE | 先に親の行を入れる。親が決まらないなら NULL にする |
| 1451 | 親の DELETE / 主キーの UPDATE | 先に子の行を消すか付け替える。ON DELETE CASCADE / SET NULL |
| 1701 | 親の TRUNCATE |
DELETE を使う |
| 3730 | 親の DROP TABLE |
先に子の外部キーを外すか子を消す |
1452(表名が #sql-...) |
既存の表に外部キーを足す ALTER TABLE |
孤児行を直してから足す |
| 3780 | 外部キーを作る | 子と親の列の型を合わせる |
| 6125 | 外部キーを作る | 親の列に主キーか一意キーを付ける |
NULL は親が無くても入る
parent_id に NULL を入れる INSERT は通りました。親が決まっていない行を許すかどうかは、列の NOT NULL で決めます。
親の側で出るエラー
表ごと消す操作は、1451 とは別の番号になります。
TRUNCATE TABLE parent;
ERROR 1701 (42000): Cannot truncate a table referenced in a foreign key constraint (`fkdb`.`child`, CONSTRAINT `child_ibfk_1`)
DROP TABLE parent;
ERROR 3730 (HY000): Cannot drop table 'parent' referenced by a foreign key constraint 'child_ibfk_1' on table 'child'.
制約の一覧を出す
制約名を付けずに作ると、子の表名_ibfk_連番 になります。どの表のどの列がどこを参照しているかは information_schema で引けます。
SELECT table_name, column_name, constraint_name, referenced_table_name, referenced_column_name
FROM information_schema.key_column_usage
WHERE table_schema = 'fkdb' AND referenced_table_name IS NOT NULL;
+------------+-------------+-----------------+-----------------------+------------------------+
| TABLE_NAME | COLUMN_NAME | CONSTRAINT_NAME | REFERENCED_TABLE_NAME | REFERENCED_COLUMN_NAME |
+------------+-------------+-----------------+-----------------------+------------------------+
| child | parent_id | child_ibfk_1 | parent | id |
+------------+-------------+-----------------+-----------------------+------------------------+
ON DELETE / ON UPDATE の設定は information_schema.referential_constraints の DELETE_RULE / UPDATE_RULE で見ます。何も指定しないと NO ACTION です。
ON DELETE CASCADE と SET NULL
親を消したときの子の扱いを外部キーに書けます。ON DELETE CASCADE の子は行ごと消え、ON DELETE SET NULL の子は parent_id が NULL になりました。
FOREIGN KEY (parent_id) REFERENCES parent(id) ON DELETE CASCADE
FOREIGN KEY (parent_id) REFERENCES parent(id) ON DELETE SET NULL
子の行が親無しでは意味を持たないなら CASCADE、親が消えても行を残したいなら SET NULL にします。
FOREIGN_KEY_CHECKS=0 で入った孤児行
SET foreign_key_checks = 0 にすると、検査されずに入ります。1 に戻しても、入った行は検査されません。
SET foreign_key_checks = 0;
INSERT INTO child VALUES (13, 99); -- 親に 99 は無い
SET foreign_key_checks = 1;
既存の表に外部キーを足す ALTER TABLE も、foreign_key_checks = 0 の間は孤児行があっても通りました。親の無い子は外部結合で探します。
SELECT c.*
FROM child c LEFT JOIN parent p ON p.id = c.parent_id
WHERE c.parent_id IS NOT NULL AND p.id IS NULL;
+----+-----------+
| id | parent_id |
+----+-----------+
| 13 | 99 |
+----+-----------+
外部キーを足すときの 1452
孤児行がある表に、検査を有効にしたまま外部キーを足すと 1452 になります。表名が作業用の一時名になるので、元の表名はメッセージに出ません。
ALTER TABLE child2 ADD CONSTRAINT fk_c2 FOREIGN KEY (parent_id) REFERENCES parent(id);
ERROR 1452 (23000): Cannot add or update a child row: a foreign key constraint fails (`fkdb`.`#sql-69d_1a`, CONSTRAINT `fk_c2` FOREIGN KEY (`parent_id`) REFERENCES `parent` (`id`))
制約名(fk_c2)から、どの ALTER TABLE かを特定します。
外部キーを作れない(3780 / 6125)
子と親で列の型が違うと作れません。int の親に bigint の子を付けた例です。
ERROR 3780 (HY000): Referencing column 'parent_id' and referenced column 'id' in foreign key constraint 'child3_ibfk_1' are incompatible.
親の列が主キーでも一意キーでもないと 6125 になります。
ERROR 6125 (HY000): Failed to add the foreign key constraint. Missing unique key for constraint 'child4_ibfk_1' in the referenced table 'parent'
8.4 では restrict_fk_on_non_standard_key が既定で ON です。親の列に一意でない普通の索引を付けても、6125 のままでした。
直前のエラーの詳細
SHOW ENGINE INNODB STATUS\G の LATEST FOREIGN KEY ERROR に、最後に失敗した文と親の索引で一番近かった行が出ます。
LATEST FOREIGN KEY ERROR
------------------------
2026-10-21 10:20:33 137221097105088 Transaction:
...
insert into child values (14, 98)
Foreign key constraint fails for table `fkdb`.`child`:
,
CONSTRAINT `child_ibfk_1` FOREIGN KEY (`parent_id`) REFERENCES `parent` (`id`)
Trying to add in child table, in index parent_id tuple:
...
But in parent table `fkdb`.`parent`, in index PRIMARY,
the closest match we can find is record:
アプリのログに SQL が残っていないとき、失敗した文を後から確かめるのに使えます。