MySQL で「Cannot delete or update a parent row」が出て行を削除できない
エラー 1451 は、削除しようとした行を他テーブルの外部キーが参照しているために出る。
子テーブル側の行を先に処理するか、外部キーに ON DELETE の参照動作を設定すれば解決する。
公開:
要約
Cannot delete or update a parent row: a foreign key constraint fails(エラー 1451)は、削除・更新しようとした行が他のテーブルの外部キーから参照されているときに出る。
外部キーの参照動作を指定しない場合の既定は RESTRICT で、参照されている親の行の削除は拒否される。
子テーブル側を先に処理するか、外部キー定義に ON DELETE の動作を設定するのが解決策である。
よくある原因
- 子の行が残っている: 削除したい親の行の主キーを、子テーブルの外部キー列がまだ参照している。
- 参照動作が未指定:
ON DELETEを指定していない外部キーは RESTRICT 扱いになり、親側の削除・更新が拒否される。 - 参照元が不明: テーブルが多いと、どの外部キーが削除を妨げているのか分からなくなる。
解決策
1. 参照元のテーブルを特定する
SELECT TABLE_NAME, COLUMN_NAME, CONSTRAINT_NAME
FROM information_schema.KEY_COLUMN_USAGE
WHERE REFERENCED_TABLE_NAME = 'parent';エラーメッセージにも制約名と参照元テーブルが表示されるので、まずどの外部キーが原因かを確定する。
2. 子テーブル側を先に処理する
DELETE FROM child WHERE parent_id = 10;
DELETE FROM parent WHERE id = 10;参照している行が無くなれば、親の行は普通に削除できる。
3. 外部キーに ON DELETE の動作を設定する
ALTER TABLE child
DROP FOREIGN KEY fk_child_parent,
ADD CONSTRAINT fk_child_parent
FOREIGN KEY (parent_id) REFERENCES parent(id)
ON DELETE CASCADE;CASCADE は親の削除に合わせて子の行も削除し、SET NULL は子の外部キー列を NULL にする(列が NULL 許容である必要がある)。
どの動作が適切かはデータの性質で決まる(FOREIGN KEY 制約の公式ドキュメント(新しいタブで開く))。
4. 一時的にチェックを外す(移行作業のみ)
SET FOREIGN_KEY_CHECKS = 0;
-- テーブル再作成やデータ移行など
SET FOREIGN_KEY_CHECKS = 1;参照整合性が壊れたデータを作れてしまうため、日常の削除操作には使わない。
ダンプの取り込みやテーブル定義の作り直しなど、整合性を自分で保証できる場面に限る。