web-dev-qa-db-ja.com

MySQLエラー1215:外部キー制約を追加できません

新しいスキーマを自分のdbサーバーに転送しようとしていますが、なぜこのエラーが発生するのかわかりません。私はここで答えを検索しようとしました、しかし私が見つけたすべてはdbエンジンをInnodbに設定するか、または私が外部キーとして使用しようとしているキーがそれら自身のテーブルの主キーであること。私が間違っていなければ、私はこれら両方のことをしました。他に何か手助けをすることができますか?

Executing SQL script in server

ERROR: Error 1215: Cannot add foreign key constraint

-- -----------------------------------------------------
-- Table `Alternative_Pathways`.`Clients_has_Staff`
-- -----------------------------------------------------

CREATE  TABLE IF NOT EXISTS `Alternative_Pathways`.`Clients_has_Staff` (
  `Clients_Case_Number` INT NOT NULL ,
  `Staff_Emp_ID` INT NOT NULL ,
  PRIMARY KEY (`Clients_Case_Number`, `Staff_Emp_ID`) ,
  INDEX `fk_Clients_has_Staff_Staff1_idx` (`Staff_Emp_ID` ASC) ,
  INDEX `fk_Clients_has_Staff_Clients_idx` (`Clients_Case_Number` ASC) ,
  CONSTRAINT `fk_Clients_has_Staff_Clients`
    FOREIGN KEY (`Clients_Case_Number` )
    REFERENCES `Alternative_Pathways`.`Clients` (`Case_Number` )
    ON DELETE NO ACTION
    ON UPDATE NO ACTION,
  CONSTRAINT `fk_Clients_has_Staff_Staff1`
    FOREIGN KEY (`Staff_Emp_ID` )
    REFERENCES `Alternative_Pathways`.`Staff` (`Emp_ID` )
    ON DELETE NO ACTION
    ON UPDATE NO ACTION)
ENGINE = InnoDB

SQLスクリプトの実行が終了しました。ステートメント:7成功、1失敗

これが親テーブルのSQLです。

CREATE  TABLE IF NOT EXISTS `Alternative_Pathways`.`Clients` (
  `Case_Number` INT NOT NULL ,
  `First_Name` CHAR(10) NULL ,
  `Middle_Name` CHAR(10) NULL ,
  `Last_Name` CHAR(10) NULL ,
  `Address` CHAR(50) NULL ,
  `Phone_Number` INT(10) NULL ,
  PRIMARY KEY (`Case_Number`) )
ENGINE = InnoDB

CREATE  TABLE IF NOT EXISTS `Alternative_Pathways`.`Staff` (
  `Emp_ID` INT NOT NULL ,
  `First_Name` CHAR(10) NULL ,
  `Middle_Name` CHAR(10) NULL ,
  `Last_Name` CHAR(10) NULL ,
  PRIMARY KEY (`Emp_ID`) )
ENGINE = InnoDB
294
Robert B

Clients.Case_NumberStaff.Emp_IDClients_has_Staff.Clients_Case_NumberClients_has_Staff.Staff_Emp_IDと全く同じデータ型ではないと思います。

おそらく、親テーブルの列はINT UNSIGNEDですか?

それらは両方のテーブルでまったく同じデータ型である必要があります。

519
Ike Walker

外部キー制約エラーが発生する可能性がある理由

  1. InnoDBをすべてのテーブルのエンジンとして使用しているわけではありません。
  2. ターゲットテーブルで存在しないキーを参照しようとしています。それがもう一方のテーブルの key であることを確認してください(これは主キーまたは固有キーになります)
  3. 列のタイプが同じではありません(参照テーブルの列がNULL可能になる可能性があります)。
  4. PK/FKがvarcharの場合は、照合が両方で同じであることを確認してください。

更新:

  1. 理由の1つは、ON DELETE SET NULLに使用している列がNULLに定義されていないことも考えられます。そのため、列がデフォルトのnullに設定されていることを確認してください。

これらを確認してください。

208
Explosion Pills

他の人にとっては、同じエラーが常に列タイプの不一致が原因であるとは限りません、あなたはコマンドを発行することによってmysql foriegnキーエラーに関するより多くの情報を見つけることができます

SHOW ENGINE INNODB STATUS;

印刷されたメッセージの上部付近に、次のようなエラーが表示される場合があります。

被参照列が最初の列として出現する被参照表に索引が見つからない、または表の列型と被参照表が制約条件に一致しません。

75
arvind

エラー1215は迷惑なものです。 Explosion Pill's answer は基本をカバーしています。あなたはそこから出発するようにしたいのです。ただし、注意すべき点が他にもあります。

たとえば、異なるテーブルのPRIMARY KEYをリンクするときは、必ず適切なON UPDATEおよびON DELETEオプションを指定してください。例えば。:

...
PRIMARY KEY (`id`),
FOREIGN KEY (`id`) REFERENCES `t` (`other_id`) ON DELETE SET NULL
....

pRIMARY KEY(idなど)をNULLにすることはできないので、飛ぶことはありません。

こういった種類の制約を追加するときには、さらにもっと微妙な問題があると思います。制約エラーに遭遇するときは、制約とその影響が現在のコンテキストで意味をなすことを常に確認してください。あなたのエラー1215で頑張ってください!

12
Domi

SHOW TABLE STATUS を使用してテーブルの照合順序を確認します。照合順序を含むテーブルに関する情報を確認できます。

両方のテーブルに同じ照合順序が必要です。

それは私に起こりました。

7
Carlos Laspina

私の場合は、SET FOREIGN_KEY_CHECKS=0を使用してテーブルを削除し、次にSET FOREIGN_KEY_CHECKS=1を使用しました。テーブルをリロードするときに、error 1215を取得しました。問題は、私が削除して再ロードしていたテーブルへの外部キーを持つ別のテーブルがデータベースにあることでした。再ロード処理の一環として、一方のフィールドのデータ型を変更すると、もう一方のテーブルの外部キーが無効になり、error 1215がトリガされます。もう1つのテーブルを削除してから、関連フィールドの新しいデータ型を再ロードすることで問題を解決しました。

7
CodeMed

Laravel 4を使用する場合、特にJeffreyWayのLaravel 4ジェネレーターを使用している場合に発生する「エラー1215:外部キー制約を追加できません」という落とし穴があります。

Laravel 4では、JeffreyWayのGeneratorsを使用して移行ファイルを生成し、テーブルを1つずつ作成できます。つまり、各移行ファイルは1つのテーブルを生成します。各移行ファイルはファイル名にタイムスタンプを付けて生成され、ファイルに順序が付けられるという事実に注意する必要があります。生成の順序は、Artisan CLIコマンド "php artisan migrate"を起動したときの移行操作の順序でもあります。そのため、ファイルが後者のファイルで生成されるがまだ生成されていないキーを参照する外部キー制約を要求した場合、エラー1215が発生します。そのような場合は、マイグレーションファイルの生成順序を調整する必要があります。適切な順序で新しいファイルを生成し、コンテンツをコピーインしてから、乱れた古いファイルを削除します。

5
user2975399

Fkを追加しようとしたときに同じエラーが発生しました。私の場合、問題は符号なしとしてマークされたFKテーブルのPKによって引き起こされました。

4
Alex

私は同じ問題を抱えていました。
これで解決しました:

私は以下の行を作成しました。
primary key: (id int(11) unsigned NOT NULL AUTO_INCREMENT)

私のスキーマビルダーでテーブルをインポートしようとした後、この解決策を見つけました。それがあなたのために働くならば、私に知らせてください!

がんばろう!

フェリペ・テルシオ

3
user3478348

私は同じ問題、私の解決策を持っていた:

前:

CREATE TABLE EMPRES
( NoFilm smallint NOT NULL

  PRIMARY KEY (NoFilm)

  FOREIGN KEY (NoFilm) REFERENCES cassettes

);

解決策:

CREATE TABLE EMPRES
(NoFilm smallint NOT NULL REFERENCES cassettes,

 PRIMARY KEY (NoFilm)

);

助けになれば幸いです。

3

もう1つの理由:ON DELETE SET NULL all を使用する場合、外部キーで使用される列はNULL値を許可しなければなりません。他の誰かが この質問 でこれを見つけました。

私の理解するところでは、それはデータの完全性に関する問題ではないでしょうが、MySQLはこの機能をサポートしていないようです(5.7)。

2
robsch

テーブルの互換性を確認してください。たとえば、一方のテーブルがMyISAMで、もう一方のテーブルがInnoDBの場合、この問題が発生する可能性があります。

2
Dennis

MySQL(INNODB)の場合...リンクしたいカラムの定義を取得する

SELECT * FROM information_schema.columns WHERE 
TABLE_NAME IN (tb_name','referenced_table_name') AND 
COLUMN_NAME  IN ('col_name','referenced_col_name')\G

両方の列定義の比較と検証

同じCOLUMN_TYPE(長さ)、同じCOLATION

のような遊びに役立つかもしれません

set foreign_key_checks=0;
ALTER TABLE tb_name ADD FOREIGN KEY(col_name) REFERENCES ref_table(ref_column) ON DELETE ...
set foreign_key_checks=1;
2
bortunac

このエラーが見つかりません

CREATE TABLE RATING (

Riv_Id INT(5),
Mov_Id INT(10) DEFAULT 0,
Stars INT(5),
Rating_date DATE, 

PRIMARY KEY (Riv_Id, Mov_Id),

FOREIGN KEY (Riv_Id) REFERENCES REVIEWER(Reviewer_ID)
ON DELETE SET NULL ON UPDATE CASCADE,

FOREIGN KEY (Mov_Id) REFERENCES MOVIE(Movie_ID)
ON DELETE SET DEFAULT ON UPDATE CASCADE
)
2
gathila

これは、列の種類が異なる場合にも発生します。

例えば参照している列がUNSIGNED INTで、参照されている列がINTの場合、このエラーが発生します。

2
Mozaffar

私は全く違う理由でこのエラーを経験しました。私は自分のデータモデル(素晴らしいツール)を作成するためにMySQL Workbench 6.3を使用しました。外部キー制約定義で定義されている列の順序が表の列の順序に合わない場合、このエラーも生成されます。

それ以外のことをすべて試してみて、それを確認するのに約4時間かかりました。

これですべてうまくいったので、コーディングに戻ることができます。 :-)

1
Stephen Nortje

ウー私はちょうどそれを手に入れました!それはすでに投稿された多くの答え(innoDB、unsignedなど)の組み合わせでした。私がここで見なかったことの1つは、あなたのFKがPKを指しているならば、ソース列が理にかなっている値を持つことを確認してください。たとえば、PKがmediumint(8)の場合は、source列にmediumint(8)も含まれていることを確認してください。それは私にとって問題の一部でした。

1
Chris Neve

私にとっては、列型でした。 BigINT!= INT.

しかし、それでもまだうまくいきませんでした。

だから私はエンジンをチェックしました。 Table1 = InnoDBおよびTable = InnoDBを確認してください。

1
Chad

参照テーブルがMyISAMエンジンを使用しているためにこのエラーが発生した場合、この回答はデータベースを変換するための素早い方法を提供しますので、すべてのDjangoモデルテーブルはInnoDBを使用します: https://stackoverflow.com/a/15389961/2950621

それはconvert_to_innodbと呼ばれるDjango管理コマンドです。

1
nmgeek

私はちょうどVARCHAR外部キーリレーションのためにもこのケースを追加したいと思いました。私は先週、MySQL Workbench 8.0でこれを解決しようとしましたが、ようやくエラーを修正することができました。

簡単な答え: スキーマ、テーブル、カラム、参照テーブル、参照カラム、および親テーブルを参照する他のテーブルの文字セットと照合順序は一致する必要があります。

長い答え: テーブルにENUMデータ型がありました。これをVARCHARに変更し、参照テーブルから値を取得できるので、追加のオプションを追加するために親テーブルを変更する必要はありません。この外部キーの関係は簡単に思えましたが、私は1215エラーを受け取りました。 arvind の答えと次の link の使用を提案しました

SHOW ENGINE INNODB STATUS;

このコマンドを使用すると、次のようなエラーの詳細な説明が表示され、追加の役立つ情報はありません

被参照列が最初の列として出現する被参照表に索引が見つからない、または表の列型と被参照表が制約条件に一致しません。 ENUMとSETの内部記憶域タイプが> = InnoDB-4.1.12で作成されたテーブルで変更され、古いテーブルのそのようなカラムを新しいテーブルのそのようなカラムから参照できないことに注意してください。正しい外部キーの定義については http://dev.mysql.com/doc/refman/8.0/en/innodb-foreign-key-constraints.html を参照してください。

その後、 Arvind Bharadwaj と/ here で示唆されているようにSET FOREIGN_KEY_CHECKS=0;を使用しました。

これにより、次のエラーメッセージが表示されました。

エラーコード:1822。外部キー制約を追加できませんでした。制約のインデックスがありません

この時点で、私はスキーマを「リバースエンジニアリング」し、EERダイアグラムで外部キーの関係を作ることができました。 'フォワードエンジニア'に関して、私は以下のエラーを受け取りました:

エラー1452:子行を追加または更新できません:外部キー制約が失敗します

EERダイアグラムを新しいスキーマにフォワードエンジニアしたとき、SQLスクリプトは問題なく実行されました。フォワードエンジニアの試みから生成されたSQLを比較すると、違いは文字セットと照合順序であることがわかりました。親表、子表、および2つの列にはutf8mb4文字セットとutf8mb4_0900_ai_ci照合順序がありましたが、親表内の別の列がCHARACTER SET = utf8 , COLLATE = utf8_bin ;を使用して別の子表に参照されていました。

スキーマ全体について、すべてのテーブルとすべての列の文字セットと照合順序を次のように変更しました。

CHARACTER SET = utf8mb4 COLLATE = utf8mb4_general_ci;

これは1215エラーでついに私の問題を解決しました。

サイドメモ: 照合utf8mb4_general_ciはMySQL Workbench 5.0以降で動作します。照合utf8mb4_0900_ai_ciはMySQL Workbench 8.0以降でのみ動作します。私が文字セットと照合順序に関して問題を抱えていた理由の1つは、MySQL Workbenchがその間に8.0にアップグレードされたことにあります。これが link です。これはこの照合についてもっと話しています。

1
CoderBapu

私の場合、ソーステーブルが存在しなかったのでFOREIGN KEYチェックを無効にしなければなりませんでした。

SET FOREIGN_KEY_CHECKS=0;

0
Arvind Bhardwaj

これはすでに述べたことの微妙なバージョンですが、私の例では、私は2つのデータベース(fooとbar)を持っていました。私は最初にfooを作成しましたが、それがbar.bazの外部キーを参照していることに気づきませんでした(まだ作成されていません)。 (外部キーなしで)bar.bazを作成しようとしたときに、このエラーが発生し続けました。しばらく見回した後、私はfooで外部キーを見つけました。

つまり、長い間、このエラーが発生した場合は、作成中のテーブルに対する既存の外部キーがある可能性があります。

0
ajon

逆引用符の使用にも注意してください。私はスクリプトの中で次のように述べました。

ALTER TABLE service ADD FOREIGN KEY (create_by) REFERENCES `system_user(id)`;

しかし、最後のバッククォートは誤りでした。それはあったはずです:

ALTER TABLE service ADD FOREIGN KEY (create_by) REFERENCES `system_user`(`id`);

MySQLはこのエラーに関して不幸なことに詳細を述べていません...

0

段階的移行を使用しているときに外部キーを作成しようとしたとき

この例のように:

ユーザーテーブル

    public function up()
{
    Schema::create('flights', function (Blueprint $table) {
        $table->increments('id');
        $table->string('name');
        $table->TinyInteger('color_id')->unsigned();
        $table->foreign('color_id')->references('id')->on('colors');
        $table->timestamps();
    });
}

色テーブル

    public function up()
{
    Schema::create('flights', function (Blueprint $table) {
        $table->increments('id');
        $table->string('color');
        $table->timestamps();
    });
}

プロパティが機能しないことがありました

[PDOException]
SQLSTATE[HY000]: General error: 1215 Cannot add foreign key constraint

[ユーザーテーブル]の外部キー(タイプ)が[カラーテーブル]の主キー(タイプ)と異なるため、このエラーが発生しました

この問題を解決するには、[colors table]の主キーを変更する必要があります。

$table->tinyIncrements('id');


主キー$table->Increments('id');を使うとき

Integerを外部キーとして使うべきです

    $table-> unsignedInteger('fk_id');
    $table->foreign('fk_id')->references('id')->on('table_name');

主キー$table->tinyIncrements('id');を使うとき

unsignedTinyIntegerを外部キーとして使うべきです

    $table-> unsignedTinyInteger('fk_id');
    $table->foreign('fk_id')->references('id')->on('table_name');

主キー$table->smallIncrements('id');を使うとき

unsignedSmallIntegerを外部キーとして使うべきです

    $table-> unsignedSmallInteger('fk_id');
    $table->foreign('fk_id')->references('id')->on('table_name');

主キー$table->mediumIncrements('id');を使うとき

unsignedMediumIntegerを外部キーとして使うべきです

    $table-> unsignedMediumInteger('fk_id');
    $table->foreign('fk_id')->references('id')->on('table_name');
0

私はパーティーにとても遅刻しているのを知っています、しかしそれがリストされるように私はそれをここに出したいと思います。

フィールドが同じように定義され、テーブルタイプも同じ照合順序を持っていることを確認するための上記のアドバイスのすべてと同様に、CHILDフィールドのデータが正しくないフィールドをリンクしようとすることのルーキーミスをしないでくださいすでにPARENTフィールドにあります。あなたがまだPARENTフィールドに入力していないCHILDフィールドにあるデータがあるなら、それはこのエラーを引き起こすでしょう。エラーメッセージがもう少し参考にならないのは残念です。

よくわからない場合は、外部キーを持つテーブルをバックアップし、すべてのデータを削除してから外部キーを作成してください。成功したら、あなたは何をすべきか!

がんばろう。

0
noowie

私にとっては、mysqldumpによって作成されたダンプファイルをインポートするときに1215エラーが発生しました。これにより、テーブルがアルファベット順に作成されます。 (指摘するためのこのページへの小道具: https://www.percona.com/blog/2017/04/06/dealing-mysql-error-code-1215-cannot-add-foreign-key-constraint /

Mysqldumpはテーブルをアルファベット順に並べ、テーブルの名前を変更したくないので、JeremyWeir このページ上 の回答の指示に従いました。ダンプファイルの先頭にset FOREIGN_KEY_CHECKS = 0;を付けて、ダンプファイルの下部にあるSET FOREIGN_KEY_CHECKS = 1;

その解決策は私のために働いた。

0
Arya

このエラーのもう1つの原因は、同じ外部キー名を持つ2つ以上の同じテーブル名があることです。これは、Mysql Workbenchのようなモデリングおよび設計ソフトウェアを使用し、後で設計からスクリプトを生成する人々に起こることがあります。

0
Dima Dz

上記の @ Explosion Pillsの回答に別の理由を追加します

7-複数列キーを使用する場合、外部キー作成の順序は、テーブル列の順序と一致する必要があります。

0
RADU