106

他の 2 つのテーブルの主キーを参照する 2 つの外部キーを使用して MySQL にテーブルを作成しようとしていますが、errno: 150 エラーが発生し、テーブルが作成されません。

3 つのテーブルすべての SQL は次のとおりです。

CREATE TABLE role_groups (
  `role_group_id` int(11) NOT NULL `AUTO_INCREMENT`,
  `name` varchar(20),
  `description` varchar(200),
  PRIMARY KEY (`role_group_id`)
) ENGINE=InnoDB;

CREATE TABLE IF NOT EXISTS `roles` (
  `role_id` int(11) NOT NULL AUTO_INCREMENT,
  `name` varchar(50),
  `description` varchar(200),
  PRIMARY KEY (`role_id`)
) ENGINE=InnoDB;

create table role_map (
  `role_map_id` int not null `auto_increment`,
  `role_id` int not null,
  `role_group_id` int not null,
  primary key(`role_map_id`),
  foreign key(`role_id`) references roles(`role_id`),
  foreign key(`role_group_id`) references role_groups(`role_group_id`)
) engine=InnoDB;

どんな助けでも大歓迎です。

4

20 に答える 20

254

私は同じ問題を抱えていましたALTER TABLE ADD FOREIGN KEY

1 時間後、エラー 150 が発生しないようにするには、次の条件を満たす必要があることがわかりました。

  1. 参照する外部キーを定義する前に、親テーブルが存在している必要があります。テーブルは正しい順序で定義する必要があります。最初に親テーブル、次に子テーブルです。両方のテーブルが相互に参照している場合は、FK 制約なしで 1 つのテーブルを作成し、次に 2 番目のテーブルを作成してから、最初のテーブルに を使用して FK 制約を追加する必要がありますALTER TABLE

  2. 2 つのテーブルは両方とも外部キー制約をサポートする必要がありますENGINE=InnoDB。他のストレージ エンジンは外部キーの定義を黙って無視するため、エラーや警告は返されませんが、FK 制約は保存されません。

  3. 親テーブルで参照される列は、キーの左端の列である必要があります。Parent のキーがPRIMARY KEYorの場合に最適ですUNIQUE KEY

  4. FK 定義は、PK 定義と同じ順序で PK 列を参照する必要があります。たとえば、FK のREFERENCES Parent(a,b,c)場合、Parent の PK は順番に列で定義してはなりません(a,c,b)

  5. 親テーブルの PK 列は、子テーブルの FK 列と同じデータ型である必要があります。たとえば、親テーブルの PK 列が である場合は、必ず子テーブル フィールドの対応する列UNSIGNEDを定義してください。UNSIGNED

    例外: 文字列の長さは異なる場合があります。たとえば、VARCHAR(10)参照することVARCHAR(20)も、その逆も可能です。

  6. 文字列型の FK 列には、対応する PK 列と同じ文字セットと照合順序が必要です。

  7. 子テーブルに既にデータがある場合、FK 列のすべての値は、親テーブルの PK 列の値と一致する必要があります。次のようなクエリでこれを確認します。

    SELECT COUNT(*) FROM Child LEFT OUTER JOIN Parent ON Child.FK = Parent.PK 
    WHERE Parent.PK IS NULL;
    

    これは、ゼロ (0) の一致しない値を返す必要があります。明らかに、このクエリは一般的な例です。テーブル名と列名を置き換える必要があります。

  8. 親テーブルも子テーブルもテーブルにすることはできませんTEMPORARY

  9. 親テーブルも子テーブルもテーブルにすることはできませんPARTITIONED

  10. オプションを使用して FK を宣言する場合ON DELETE SET NULL、FK 列は null 許容である必要があります。

  11. 外部キーの制約名を宣言する場合、制約名は、制約が定義されているテーブル内だけでなく、スキーマ全体で一意である必要があります。2 つのテーブルに、同じ名前の独自の制約を設定することはできません。

  12. 新しい FK を作成しようとしている同じフィールドを指している他のテーブルに他の FK があり、それらが不正な形式 (つまり、異なる照合) である場合は、最初に整合性を保つ必要があります。SET FOREIGN_KEY_CHECKS = 0;これは、誤って定義された一貫性のない関係で使用された過去の変更の結果である可能性があります。これらの問題の FK を特定する方法については、以下の @andrewdotn の回答を参照してください。

お役に立てれば。

于 2011-01-12T20:39:06.183 に答える
65

MySQL の一般的な「errno 150」メッセージ「<a href="http://dev.mysql.com/doc/refman/5.5/en/create-table-foreign-keys.html" rel="noreferrer">は、外部キー制約が正しく形成されていませんでした。」このページを読んでいる方はすでにお気づきかもしれませんが、一般的な「errno: 150」エラー メッセージは本当に役に立ちません。でも:

実際のエラー メッセージは、実行して出力SHOW ENGINE INNODB STATUS;を探すことで取得できます。LATEST FOREIGN KEY ERROR

たとえば、外部キー制約を作成しようとすると、次のようになります。

CREATE TABLE t1
(id INTEGER);

CREATE TABLE t2
(t1_id INTEGER,
 CONSTRAINT FOREIGN KEY (t1_id) REFERENCES t1 (id));

エラーで失敗しますCan't create table 'test.t2' (errno: 150)。それは、それが外部キーの問題であること以外に有用なことは誰にもわかりません。しかし、実行するSHOW ENGINE INNODB STATUS;と、次のように表示されます。

------------------------
LATEST FOREIGN KEY ERROR
------------------------
130811 23:36:38 Error in foreign key constraint of table test/t2:
FOREIGN KEY (t1_id) REFERENCES t1 (id)):
Cannot find an index in the referenced table where the
referenced columns appear as the first columns, or column types
in the table and the referenced table do not match for constraint.

問題は、インデックスが見つからないことです。SHOW INDEX FROM t1table のインデックスがまったくないことを示していますt1。たとえば、で主キーを定義して修正するt1と、外部キー制約が正常に作成されます。

于 2013-08-12T05:47:01.897 に答える
25

制約でリンクしようとしている 2 つのフィールドのプロパティがまったく同じであることを確認してください。

多くの場合、ID 列の「署名されていない」プロパティが原因です。

ALTER TABLE `dbname`.`tablename` CHANGE `fieldname` `fieldname` int(10) UNSIGNED NULL;
于 2009-10-27T15:58:25.327 に答える
10

このスクリプトを実行したときのデータベースの現在の状態は? 完全に空ですか?データベースを最初から作成する場合、SQLは問題なく実行されますが、errno 150は通常、外部キーの一部であるテーブルの削除と再作成に関係しています。100% 新鮮で新しいデータベースで作業していないように感じます。

SQL ファイルを「source」するときにエラーが発生した場合は、「source」コマンドの直後に MySQL プロンプトから「SHOW ENGINE INNODB STATUS」コマンドを実行して、より詳細なエラー情報を表示できるはずです。

マニュアル エントリも参照してください。

削除されたテーブルを再作成する場合は、それを参照する外部キー制約に準拠する定義が必要です。前述のように、正しい列名と型が必要であり、参照されるキーにインデックスが必要です。これらが満たされていない場合、MySQL はエラー番号 1005 を返し、エラー メッセージでエラー 150 を参照します。MySQL が CREATE TABLE ステートメントからエラー番号 1005 を報告し、エラー メッセージがエラー 150 を参照している場合、外部キー制約が正しく形成されていないため、テーブルの作成が失敗しました。

MySQL 5.1 リファレンス マニュアル.

于 2009-09-21T23:14:16.307 に答える
5

このスレを見て同じ悩みを抱えている方へ

このようなエラーが発生する理由はたくさんあります。MySQL の外部キー エラーの原因と解決策のかなり完全なリスト (ここで説明したものを含む) については、次のリンクを参照してください。

MySQL 外部キー エラーと Errno 150

于 2012-06-12T23:44:40.767 に答える
4

Google 経由でこの SO エントリを見つけた他のユーザーの場合: 「NOT NULL」と定義された外部キー (になる) 列に対して SET NULL アクションを実行しようとしていないことを確認してください。CHECK ENGINE INNODB STATUS を実行することを思い出すまで、それは大きなフラストレーションの原因でした。

于 2012-02-23T12:48:57.830 に答える
3

最初に確認してください

  1. InnoDB テーブルを使用しています。
  2. FOREIGN KEY のフィールドは、ソース フィールドと同じ型と長さ (!) を持っています。

私は同じ問題を抱えていて、それを修正しました。1 つのフィールドに符号なし INT を使用し、他のフィールドには整数のみを使用しました。

于 2016-05-29T13:25:02.003 に答える
3

SHOW ENGINE INNODB STATUS;@andrewdotn が指摘したように、最善の方法は、単なるエラー コードではなく、詳細な error( ) を確認することです。

理由の 1 つは、同じ名前のインデックスが既に存在している可能性があり、別のテーブルにある可能性があります。慣例として、このような衝突を避けるために、インデックス名の前にテーブル名をプレフィックスすることをお勧めします。たとえば、代わりにidx_userId使用しますidx_userActionMapping_userId

于 2015-06-04T04:18:04.590 に答える
1

これは通常、既存のデータベースにファイルをソースしようとしたときに発生します。最初にすべてのテーブル (または DB 自体) をドロップします。そしてSET foreign_key_checks = 0;、最初とSET foreign_key_checks = 1;最後にあるソースファイル。

于 2013-03-27T20:14:13.957 に答える
1

これが失敗する別の理由を見つけました...大文字と小文字を区別するテーブル名。

このテーブル定義の場合

CREATE TABLE user (
  userId int PRIMARY KEY AUTO_INCREMENT,
  username varchar(30) NOT NULL
) ENGINE=InnoDB;

このテーブル定義は機能します

CREATE TABLE product (
  id int PRIMARY KEY AUTO_INCREMENT,
  userId int,
  FOREIGN KEY fkProductUser1(userId) REFERENCES **u**ser(userId)
) ENGINE=InnoDB;

一方、これは失敗します

CREATE TABLE product (
  id int PRIMARY KEY AUTO_INCREMENT,
  userId int,
  FOREIGN KEY fkProductUser1(userId) REFERENCES User(userId)
) ENGINE=InnoDB;

Windows では動作し、Unix では失敗したという事実を理解するのに数時間かかりました。それが他の誰かを助けることを願っています。

于 2014-08-02T05:54:17.980 に答える
1

Mac OS 用の MySQL Workbench 6.3。

問題: DB ダイアグラムでフォワード エンジニアリングを実行しようとすると、テーブル X で errno 150 が発生し、21 のうち 20 が成功し、1 が失敗しました。テーブル X の FK が削除された場合、以前は失敗していなかった別のテーブルにエラーが移動しました。

すべてのテーブル エンジンを myISAM に変更したところ、問題なく動作しました。

ここに画像の説明を入力

于 2015-08-24T04:44:13.607 に答える
0

外部キーが親で一意としてリストされていないことを確認してください。私はこれと同じ問題を抱えていましたが、それを一意ではないものとして区別することで解決しました。

于 2013-06-04T15:21:56.670 に答える
0

また、誤って間違ったデータベースを操作していないことを確認する価値があります。外部テーブルが存在しない場合、このエラーが発生します。なぜMySQLはそれほど不可解でなければならないのですか?

于 2013-01-22T14:27:21.123 に答える
0

私の場合、外部キーフィールドであるフィールドの名前が長すぎることが原因でした。foreign key (some_other_table_with_long_name_id). sth を短くしてみてください。その場合、エラー メッセージは少し誤解を招きます。

また、@Jon が前述したように、フィールド定義は同じでなければなりません (unsignedサブタイプに注意してください)。

于 2014-10-07T12:48:35.250 に答える
0

テーブルを作成する前に以下の行を実行します: SET FOREIGN_KEY_CHECKS = 0;

FOREIGN_KEY_CHECKS オプションは、 InnoDB テーブルの外部キー制約をチェックするかどうかを指定します。

-- 外部キー制約をチェックするように指定します (これがデフォルトです)。

SET FOREIGN_KEY_CHECKS = 1;

 

-- 外部キー制約をチェックしない

SET FOREIGN_KEY_CHECKS = 0;

いつ使用するか: 参照制約を一時的に無効にする (FOREIGN_KEY_CHECKS を 0 に設定する) と、テーブルを再作成し、任意の親子順序でデータをロードする必要がある場合に役立ちます。

于 2019-09-06T11:50:53.020 に答える