ALTER TABLE ADD FOREIGN KEY
でも同じ問題が発生しました 。
1時間後、エラー150が発生しないようにするには、これらの条件が満たされている必要があることがわかりました。
-
親テーブルは、それを参照する外部キーを定義する前に存在している必要があります。テーブルを正しい順序で定義する必要があります。最初に親テーブル、次に子テーブルです。両方のテーブルが相互に参照している場合は、FK制約なしで1つのテーブルを作成し、次に2番目のテーブルを作成してから、
ALTER TABLE
を使用して最初のテーブルにFK制約を追加する必要があります。 。 -
2つのテーブルは、両方とも外部キー制約をサポートしている必要があります。つまり、
ENGINE=InnoDB
。他のストレージエンジンは外部キー定義を黙って無視するため、エラーや警告は返されませんが、FK制約は保存されません。 -
親テーブルで参照される列は、キーの左端の列である必要があります。親のキーが
PRIMARY KEY
の場合に最適です またはUNIQUE KEY
。 -
FK定義は、PK定義と同じ順序でPK列を参照する必要があります。たとえば、FK
REFERENCES Parent(a,b,c)
の場合 その場合、親のPKを(a,c,b)
の順序で列に定義してはなりません。 。 -
親テーブルのPK列は、子テーブルのFK列と同じデータ型である必要があります。たとえば、親テーブルのPK列が
UNSIGNED
の場合 、必ずUNSIGNED
を定義してください 子テーブルフィールドの対応する列。例外:文字列の長さが異なる場合があります。例:
VARCHAR(10)
VARCHAR(20)
を参照できます またはその逆。 -
文字列タイプのFK列は、対応するPK列と同じ文字セットと照合を使用する必要があります。
-
子テーブルにすでにデータがある場合、FK列のすべての値は、親テーブルのPK列の値と一致する必要があります。次のようなクエリでこれを確認してください:
SELECT COUNT(*) FROM Child LEFT OUTER JOIN Parent ON Child.FK = Parent.PK WHERE Parent.PK IS NULL;
これは、ゼロ(0)の一致しない値を返す必要があります。明らかに、このクエリは一般的な例です。テーブル名と列名を置き換える必要があります。
-
親テーブルも子テーブルも
TEMPORARY
にすることはできません テーブル。 -
親テーブルも子テーブルも
PARTITIONED
にすることはできません テーブル。 -
ON DELETE SET NULL
を使用してFKを宣言する場合 オプションの場合、FK列はnull許容である必要があります。 -
外部キーの制約名を宣言する場合、制約名は、制約が定義されているテーブルだけでなく、スキーマ全体で一意である必要があります。 2つのテーブルには、同じ名前の独自の制約がない場合があります。
-
新しいFKを作成しようとしている同じフィールドを指している他のテーブルに他のFKがあり、それらが不正な形式(つまり、異なる照合)である場合は、最初に一貫性を保つ必要があります。これは、
SET FOREIGN_KEY_CHECKS = 0;
での過去の変更の結果である可能性があります 誤って定義された一貫性のない関係で利用されました。これらの問題のあるFKを特定する方法については、以下の@andrewdotnの回答を参照してください。
これがお役に立てば幸いです。