偽の外部キー制約が失敗する


110

次のエラーメッセージが表示されます。

エラー1217(23000)、40行目:親行を削除または更新できません:外部キー制約が失敗します

...テーブルを削除しようとすると:

DROP TABLE IF EXISTS `area`;

...このように定義されます:

CREATE TABLE `area` (
  `area_id` char(3) COLLATE utf8_spanish_ci NOT NULL,
  `nombre_area` varchar(30) COLLATE utf8_spanish_ci NOT NULL,
  `descripcion_area` varchar(100) COLLATE utf8_spanish_ci NOT NULL,
  PRIMARY KEY (`area_id`),
  UNIQUE KEY `nombre_area_UNIQUE` (`nombre_area`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_spanish_ci;

おもしろいのは、外部キーを持つスキーマの他のすべてのテーブルをすでに削除したことareaです。実際には、データベースはareaテーブルを除いて空です。

データベースに他のオブジェクトがない場合、どうすれば子行を持つことができますか?私の知る限り、InnoDBは他のスキーマの外部キーを許可していませんか?

RENAME TABLE area TO something_elseコマンドを実行することもできます:-?)


テーブルが別のスキーマの参照整合性関係の一部である可能性はありますか?
Raj More

私はアプリのいくつかの他のコピーを持っているので、それは常に可能です。ただし、私が使用する構文は基本的CONSTRAINT fk_servicio_area1 FOREIGN KEY (area_id) REFERENCES area (area_id)にです。つまり、テーブル参照にスキーマ名がありません:-?
アルバロ・ゴンサレス

回答:


101

2つの可能性:

  1. FK参照を持つ別のスキーマ(mysql用語では「データベース」)内にテーブルがあります
  2. innodb内部データディクショナリはmysqlと同期していません。

ドロップが失敗した後に「SHOW ENGINE INNODB STATUS」を実行すると、どのテーブルであったか(いずれにせよ)を確認できます。

後者の場合は、可能であればサーバー全体をダンプして復元します。

MySQL 5.1以降では、エラーメッセージにFKを含むテーブルの名前が表示されます。


1
問題を再現できなくなった。同期していない辞書は、考えられる理由として際立っています。私はそれを一日テストして、どんなSHOW ENGINE INNODB STATUS報告を見るでしょう。
アルバロゴンサレス

3
この回答ありがとうございます!ドロップできなかったテーブルを参照する多対多のテーブルがまだあったため、最初にそのテーブルをドロップする必要がありました。
クリスチャンOudard

5
SHOW ENGINE INNODB STATUSは、「最新の外部キーエラー」の下に最後の外部キーエラーをリストします。これにはタイムスタンプがあります。
bbrame 14

サブジェクトテーブルへの参照キーがまだあるテーブルが存在する可能性があります。私の場合はこんな感じでした。
RT

多くの時間を節約しました。「LATEST FOREIGN KEY ERROR」の下にデータベースをドロップしました
Sand1512

121

オンデマンドで、今答えとして...

MySQLクエリブラウザまたはphpMyAdminを使用すると、クエリごとに新しい接続が開かれるように見えます( bugs.mysql.com/bug.php?id=8280)、1つのクエリですべてのドロップステートメントを記述する必要があります。

SET FOREIGN_KEY_CHECKS=0; 
DROP TABLE my_first_table_to_drop; 
DROP TABLE my_second_table_to_drop; 
SET FOREIGN_KEY_CHECKS=1; 

SET FOREIGN_KEY_CHECKS=1追加のセキュリティ対策として機能する場所...


2
phpMyAdminを使用してダンプを作成する場合は、「外部キーチェックを無効にする」オプションがあり、自動的にSET FOREIGN_KEY_CHECKS=0;ダンプの先頭に追加されます。
マイク

phpMyAdminがこの素敵な機能を実装したようですが、今はmysqlWorkbenchが同じことをするのを待っています!:)
Karlis Rode

@CodeMed FYI、私はMarkRの回答を受け入れました。MarkRの回答は理にかなっている問題の説明を提供しているからです。ただし、この同じ問題に6年以内に一度も直面していないため、確認できなかったことは認めます。これと以前の回答は回避策を提供しますが(それはすばらしいことです)、実際には質問自体に対処しないでください。
アルバロゴンサレス

1
警告:これは解決策ではなく、怠惰な人の回避策です。(削除された表を指して、いくつかの他のテーブル上のレコードで)これを使用した後、あなたは致命的な一貫性(壊れ外部キーぶら下がっ経験するCでのACIDデータベースのを)し、あなたのアプリケーションはすべての場所で例外をスローするために開始しますが。あなたは警告されました。
2017

私はbekceの警告を理解して注意する必要があると確信していますが、この解決策はうまくいきました。問題のある外部キー制約のあるテーブルを指しているすべてのテーブルもドロップしていると確信していた場合です。
user1147171 2017

47

外部キーチェックを無効にする

SET FOREIGN_KEY_CHECKS=0

62
正しいコマンドが表示されSET FOREIGN_KEY_CHECKS=0、エラーメッセージは修正されます。これが必要な理由について何か考えがありますか?テーブルがなくなった後でも外部キーはキャッシュされますか?
アルバロ・ゴンサレス

1
実を言うと、このような問題が発生する理由はわかりませんが、大きな変更や更新を行うたびにキーチェックを無効にしてください。それは何度か私に起こり、何日も眠りにつけられませんでした。
Flakron Bytyqi 2010

55
SET FOREIGN_KEY_CHECKS=1;完了したら必ず確認してください。
pedro_sland 2010年

5
MySQLクエリブラウザまたはphpMyAdminを使用する場合、クエリごとに新しい接続が開かれているように見え(bugs.mysql.com/bug.php?id=8280)、1つのクエリですべてのドロップステートメントを記述する必要があります。SET FOREIGN_KEY_CHECKS=0; DROP TABLE my_first_table_to_drop; DROP TABLE my_second_table_to_drop; SET FOREIGN_KEY_CHECKS=1; SET FOREIGN_KEY_CHECKS = 1が追加のセキュリティ対策として機能する場合
Karlis Rode

1
@ KarlisRode、phpMyAdminへのコメントのためのBravo。それを答えにするとしたら、+ 1します。
Sablefoste 2013

28

このブログから

外部キーチェックを一時的に無効にすることができます。

SET FOREIGN_KEY_CHECKS=0;

いじり終わったら、必ず復元してください。

SET FOREIGN_KEY_CHECKS=1;

私がローカルで開発していたのでいい答えです:)
アデリン

これは有効な回避策です(私はそれが機能することを確認できます)が、リンクされたブログエントリはこの質問のシナリオ(実際には1つのテーブルを保存するために空になっているデータベース)について話していません。
アルバロ・ゴンサレス

6

うまくいけば、その仕事

SET foreign_key_checks = 0; ドロップテーブルtable name; SET foreign_key_checks = 1;


はい、それはうまくいきます、以前に言及された数回のように;-)
アルバロ・ゴンサレス

1

Railsでは、を使用して次のことができますrails console

connection = ActiveRecord::Base.connection
connection.execute("SET FOREIGN_KEY_CHECKS=0;")

0

以前にこのテーブルで作業しているときにエラーを受け取った可能性があります。テーブルの名前を変更して、もう一度削除してみてください。

ALTER TABLE `area` RENAME TO `area2`;
DROP TABLE IF EXISTS `area2`;

0

簡単な解決策を見つけ、データベースをエクスポートし、テキストエディターで編集したいものを編集してからインポートします。できた


4
これは興味深い解決策ですが、実際には起こらないはずです。代わりに、変更が必要なものはすべてDBMSを介して実行する必要があります。テキストエディターでデータベースダンプを編集することは、問題の熟した道のようです。
Brandon Anzaldi、2016年

1
私はあなたが何をしているのか本当に理解していません。データベースをCREATE TABLEダンプし、コードを削除してダンプを再度ロードしても、MySQLはテーブルを削除しません。そして、ダンプを新しいデータベースに復元するつもりなら...もし私のようにすべてのテーブルを一掃したいなら、新しく作成されたデータベースはすでに空です。一部のテーブルを保持したい場合は、SET FOREIGN_KEY_CHECKS=0ここで説明されている回避策が適切に機能し、簡単になります。データの新しいコピーには非同期のデータディクショナリがない可能性があるため、おそらくダンプを編集する必要はありません。
アルバロ・ゴンサレス

-1

親行を削除または更新できません:外部キー制約が失敗しました(table1user_role、CONSTRAINT FK143BF46A8dsfsfds@#5A6BD60FOREIGN KEY(user_id)REFERENCES userid))

2つの簡単なステップで私がしたこと。最初に私はのような子テーブルの子行を削除します

mysql> table2から削除します。ここでrole_id = 2 && user_id = 20;

クエリは正常、1行が影響を受けた(0.10秒)

親を削除する第2ステップ

id1 = 20のtable1から削除します。

クエリは正常、1行が影響を受けた(0.12秒)

これで私は問題を解決します

私はあなたがそれを得たと思います。:)


もう一度質問を読んでください。存在しないテーブルは削除できません。
アルバロ・ゴンサレス

このシナリオでは、外部キー制約を削除してから、テーブルを削除してみることができます。このALTER TABLE <TABLE_NAME> DROP CONSTRAINT <FOREIGN_KEY_NAME>のように外部キーを削除できます
Aadil Masavir '20年
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.