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


334

新しいスキーマを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

6
親テーブルのスキーマを投稿してください:ClientsStaff
Ike Walker


1
@Denis OPは列が親テーブルのPKであることを確認したと言っているので、おそらく重複ではありません。
Ike Walker

要求に応じて、クライアントテーブルとスタッフテーブルのSQLステートメントを追加しました。
Robert B

回答:


591

私はそれを推測しているClients.Case_Number、および/またはStaff.Emp_ID正確でないと同じデータ型Clients_has_Staff.Clients_Case_NumberClients_has_Staff.Staff_Emp_ID

おそらく、親テーブルの列はINT UNSIGNED

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


10
ありがとう。これが問題であることが判明しました。Staff.Emp_IDはSMALLINTでしたが、参照している列はINTでした。時々それは小さなことです...
ロバートB

Tks。私の場合、子テーブルの外部キーの「ZeroFill」を誤ってクリックしたため、親テーブルの列と正確に一致しませんでした。
wwkudu 2014年

12
また、文字セットが異なる場合もあります。1つの列にutf8文字セットがあり、他の列にlatin1があるという問題がありました。ALTER TABLE TableCHARACTER SET = utf8で簡単に修正できます。ALTER TABLE DeviceCHANGE COLUMN ID IDCHAR(36)CHARACTER SET 'utf8' NOT NULL;
www.jensolsson.se

3
@ www.jensolsson.se正解です。PKに1つ以上の文字列列が含まれている場合、それらは同じ文字セット照合順序を使用する必要があります。この特定のケースでは、PKはINTであったため、テーブルや列の文字セットは関係ありませんでした。
Ike Walker

2
照合順序は私の問題であり、latin1とutf8です(表と列を確認してください)。
ben_979 2016

244

外部キー制約エラーが発生する理由:

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

更新:

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

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


14
FKが文字列にある場合は、同じ文字セットと照合順序である必要があると考えます。(または、おそらく1バイト文字セットと2バイト文字セットは互換性がありません。)
Graham Charles

5
私の理由は、最初の1つ「InnoDBとMyISAMの2つのテーブルで異なるDBエンジン」を指摘したことです
Randika Vishman

7
もう1つの理由=) `` `ON DELETE CASCADE ON UPDATE SET NULL:` ``一部の列がNOT NULLとして定義されていますが、SET NULL条件を定義しました。したがって、私はFK定義を修正するだけです。
alexglue 2015年

1
また、失敗する可能性は、ターゲットフィールドにインデックスないことです
ポールT.ローキーン2016年

1
いいですね、4点目は私の問題でした。それはちょっと厄介です-しかし、mysqlがクラッシュしたことを非常に嬉しく思います
Sebas

85

他の場合、同じエラーが必ずしも列タイプの不一致が原因であるとは限りません。コマンドを発行することにより、mysql foriegnキーエラーの詳細を確認できます。

SHOW ENGINE INNODB STATUS;

印刷されたメッセージの上部近くのようなエラーを見つけるかもしれません

参照列が最初の列として表示される参照テーブルでインデックスが見つからないか、テーブルの列タイプと参照テーブルが制約と一致していません。


13
これは診断に役立つため、私が考える最良の答えです!ありがとう。
alexglue 2015年

それはどのように機能しますか?両方のクエリを続けて実行しますか?
C4d 2016年

@ C4u、はい、両方のクエリを続けて実行する必要があります。最初にSHOW ENGINE INNODB STATUSを実行し、次に他のクエリを実行する必要があります
sureshd

PHPMyAdminでそれを行うことはできません。コマンドプロンプトで行います。
ruwan800 2017年

13

エラー1215は迷惑なものです。Explosion Pillの答えは基本をカバーしています。必ずそこから始めましょう。ただし、注意が必要なケースがさらに多くあります。

あなたが別のテーブルの主キーをリンクしようとすると、例えば、適切な提供することを確認ON UPDATEし、ON DELETEオプションを。例えば:

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

PRIMARY KEY(などid)は使用できないため、飛行しませんNULL

私は、これらの種類の制約を追加するときにさらに同様に微妙な問題があると確信しています。そのため、制約エラーが発生した場合は、常に、制約とその影響が現在のコンテキストで意味があることを確認してください。エラー1215で頑張ってください!


1
存在しない外部キーを削除しようとした場合にもこのエラーが発生します:)
Explosion Pills

2
また、ドキュメントから:MySQLは外部キーと参照されたキーのインデックスを必要とするため、外部キーのチェックが高速になり、テーブルスキャンが不要になります。参照テーブルには、外部キー列が同じ順序で最初の列としてリストされているインデックスが必要です。このようなインデックスは、存在しない場合、参照テーブルに自動的に作成されます。外部キー制約を適用するために使用できる別のインデックスを作成すると、このインデックスは後で黙って削除される可能性があります。index_nameが指定されている場合は、前述のように使用されます。
Jonathan M

1
それが私がここに来た理由です。ON DELETE SET NULL私はなりたい列に外部キーを作成しようとしましたNOT NULL。ケーキも食べられないとしよう。
Martin Hennings、2015年

8

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

両方のテーブルの照合順序は同じである必要があります。

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


これは私の場合の問題でした-MySQLエラーはまったく役に立ちません!
2018

7

私の場合、を使用してテーブルを削除しSET FOREIGN_KEY_CHECKS=0、その後で削除しましたSET FOREIGN_KEY_CHECKS=1。私は、テーブルを再ロードするために行ったとき、私は得ましたerror 1215。問題は、削除して再ロードしたテーブルへの外部キーを持つデータベース内の別のテーブルがあったことです。リロードプロセスの一部には、フィールドの1つのデータ型の変更が含まれ、他のテーブルの外部キーが無効になり、トリガーされましたerror 1215。関連するフィールドの新しいデータ型を使用して、他のテーブルを削除してから再読み込みすることで問題を解決しました。


5

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

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


4

fkを追加しようとしたときに同じエラーが発生しました。私の場合、問題はFKテーブルのPKが未署名としてマークされていることが原因でした。


3

私は同じ問題がありました、私の解決策:

前:

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)

);

それがお役に立てば幸いです;)


1
最初のCREATEでいくつかのコンマを忘れました
DLight

3

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

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

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

幸運を!

フェリペテルシオ


3

私もこのケースを追加したかっただけです VARCHAR外部キー関係にです。私は先週、MySQL Workbench 8.0でこれを理解しようと試み、最終的にエラーを修正することができました。

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

長い回答: テーブルにENUMデータ型がありました。これをに変更VARCHARし、参照テーブルから値を取得できるので、親テーブルを変更してオプションを追加する必要がありません。この外部キーの関係は簡単に見えましたが、1215エラーが発生しました。arvindの回答と次のリンクは、

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ここのリンクが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にアップグレードされたことによるものと考えています。この照合について詳しく説明しているリンクは次のとおりです。


2

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

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

これは、列のタイプが同じでない場合にも発生します。

たとえば、参照している列がUNSIGNED INTであり、参照している列がINTである場合、このエラーが発生します。


2

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

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


2

別の理由:外部キーで使用されるON DELETE SET NULL すべての列を使用する場合は、null値を許可する必要があります。他の誰かがこの質問これを発見しました。

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


1

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

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


1

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


1

私にとっては、列のタイプでした。BigINT!= INT。

しかし、それでも機能しませんでした。

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


1

まったく別の理由でこのエラーが発生しました。MySQL Workbench 6.3を使用してデータモデル(素晴らしいツール)を作成しました。外部キー制約定義で定義された列の順序がテーブルの列シーケンスに適合しない場合にも、このエラーが生成されることに気付きました。

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

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


それはどういう意味ですか?
Yazan Jaber 2017

2
@YazanJaber私は彼がこれを意味すると思います:InnoDBは、外部キーがインデックス列または列のグループを参照することを許可します。ただし、参照されるテーブルには、参照される列が同じ順序で最初の列としてリストされるインデックスが必要です。
robsch 2017年

1

laravelマイグレーションを使用しているときに外部キーを作成しようとしたとき

この例のように:

ユーザーテーブル

    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

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

この問題を解決するには、[色テーブル]の主キーを変更する必要があります

$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');

これは私を助けます。bigIncrements主キーとして持っていたので、使用する必要がありましたunsignedBigInteger
jagad89


0

バッククォートの使用にも注意してください。スクリプトに次のステートメントが含まれていました

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

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


0

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

フィールドが同じように定義され、テーブルタイプも同じ照合であることを確認するための上記のアドバイスのすべてと同様に、CHILDフィールドのデータが存在しないフィールドをリンクしようとする新人の間違いを犯さないようにしてください。すでにPARENTフィールドにあります。まだ親フィールドに入力していないデータが子フィールドにある場合、このエラーが発生します。エラーメッセージがもう少し役に立たないのは残念です。

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

幸運を。


0

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

つまり、簡単に言えば、このエラーが発生した場合、作成中のテーブルに既存の外部キーがある可能性があります。


0

私にとって、で作成されたダンプファイルをインポートするときに1215エラーが発生しましたmysqldump。これにより、テーブルがアルファベット順に作成されます。これにより、外部キーがファイルの後半に作成されたテーブルを参照するようになりました。(それを指摘するためのこのページへの小道具: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

だから私は上記の修正をすべて試しましたが、運はありませんでした。テーブルにエラーがない可能性があります。原因が見つからず、エラー1215が発生し続けました。この修正を使用しました。

phpMyAdminのローカル環境で、問題のテーブルからデータをエクスポートしました。CSV形式を選択しました。phpMyAdminでテーブルを選択した状態で、「More-> Options」を選択しました。ここで、「テーブルを(database.table)にコピーします。「構造のみ」を選択します。テーブルの名前を変更します。現在のテーブル名の横に「コピー」という単語を追加するだけです。「実行」をクリックします。これにより、新しいテーブル。新しいテーブルをエクスポートして、新しいサーバーまたは他のサーバーにインポートします。ここでもphpMyAdminを使用しています。インポートしたら、テーブルの名前を元の名前に戻します。新しいテーブルを選択し、インポートを選択します。フォーマットはCSVを選択してください。[外部キーチェックを有効にする]をオフにします。[実行]を選択します。これまでのところ、すべて正常に機能しています。

私は自分の修正をブログに投稿しました


-1

私も同じ問題を抱えていました。そして、障害はFKのテーブルPKの「署名されていない」マーカーにありました


-6

一度同じエラーが発生しました。MySQLサーバーを再起動して問題を修正しただけです。


これは問題をまったく修正しません。
James111
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.