既存のテーブルに外部キーを追加する


324

「katalog」というテーブルに外部キーを追加したい。

ALTER TABLE katalog 
ADD CONSTRAINT `fk_katalog_sprache` 
FOREIGN KEY (`Sprache`)
REFERENCES `Sprache` (`ID`)
ON DELETE SET NULL
ON UPDATE SET NULL;

これを実行しようとすると、次のエラーメッセージが表示されます。

Error Code: 1005. Can't create table 'mytable.#sql-7fb1_7d3a' (errno: 150)

INNODBステータスのエラー:

120405 14:02:57テーブルmytable。#sql-7fb1_7d3aの外部キー制約のエラー:

FOREIGN KEY (`Sprache`)
REFERENCES `Sprache` (`ID`)
ON DELETE SET NULL
ON UPDATE SET NULL:
Cannot resolve table name close to:
(`ID`)
ON DELETE SET NULL
ON UPDATE SET NULL

このクエリを使用すると機能しますが、「削除時」のアクションが間違っています。

ALTER TABLE `katalog` 
ADD FOREIGN KEY (`Sprache` ) REFERENCES `sprache` (`ID` )

どちらのテーブルもInnoDBであり、両方のフィールドは「INT(11)not null」です。MySQL 5.1.61を使用しています。MacBook ProのMySQL Workbench(最新)でこのALTERクエリを実行しようとしています。

テーブル作成ステートメント:

CREATE TABLE `katalog` (
`ID` int(11) unsigned NOT NULL AUTO_INCREMENT,
`Name` varchar(50) COLLATE utf8_unicode_ci NOT NULL,
`AnzahlSeiten` int(4) unsigned NOT NULL,
`Sprache` int(11) NOT NULL,
PRIMARY KEY (`ID`),
UNIQUE KEY `katalogname_uq` (`Name`)
 ) ENGINE=InnoDB AUTO_INCREMENT=12 DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci ROW_FORMAT=DYNAMIC$$

CREATE TABLE `sprache` (
`ID` int(11) NOT NULL AUTO_INCREMENT,
 `Bezeichnung` varchar(45) NOT NULL,
 PRIMARY KEY (`ID`),
 UNIQUE KEY `Bezeichnung_UNIQUE` (`Bezeichnung`),
KEY `ix_sprache_id` (`ID`)
) ENGINE=InnoDB AUTO_INCREMENT=3 DEFAULT CHARSET=utf8

1
の出力を投稿しなかったのでSHOW CREATE TABLE、私は質問しかできません-列名は本当に大文字でIDですか?
NB

まあ、それkatalogは今すぐ見つけるのが簡単です- 持っていint(11) unsignedます。spracheにはusignedパーツがないため、2つの列は同じではありません。
NB

つまり、両方のプライマリフィールドは同じデータ型である必要がありますか?
frgtv10

2
これは設計の問題です。最初に、2つのauto_increment列を参照していますが、これは問題です。また、MySQLのマニュアルには次のように記載されていCorresponding columns in the foreign key and the referenced key must have similar internal data types inside InnoDB so that they can be compared without a type conversion. The size and sign of integer types must be the same. The length of string types need not be the same. For nonbinary (character) string columns, the character set and collation must be the same.ます。したがって、はい、同様のデータ型と同じ符号。
NB

2
2つのauto_incrementフィールドを参照していません。katalog.Sprache(自動ではない)-> sprache.ID(自動)
frgtv10

回答:


560

外部キー(grade_id)を既存のテーブル(ユーザー)に追加するには、次の手順に従います。

ALTER TABLE users ADD grade_id SMALLINT UNSIGNED NOT NULL DEFAULT 0;
ALTER TABLE users ADD CONSTRAINT fk_grade_id FOREIGN KEY (grade_id) REFERENCES grades(id);

12
理由は私が理解し、覚えるのに役立ちます。これは、署名されていないフィールドに外部キーを追加できないためですよね?
PixMach 2015

8
@PixMach、答えはノーです。署名付き整数を外部キーとして使用できます。NBが質問で述べたように、フィールドのタイプと符号は一致する必要があります。したがって、ルックアップテーブルの主キーがUNSIGNEDの場合、外部キーフィールドもUNSIGNEDである必要があります。主キーフィールドがSIGNEDの場合、外部キーフィールドも署名する必要があります。このように考えてください。1つのテーブルの列がSHOW CREATE TABLEのように定義されていても、他のテーブルでも同じ定義を持っている必要があります。
ベン・キーン

1
これは、単一のクエリでも実行できることに注意してください(失敗した場合などに適しています)
Stijn de Witt

6
「SET FOREIGN_KEY_CHECKS = 0;」を実行する必要がありました。ADD CONSTRAINTコマンドまたはSQLを実行する前に、「子行を追加または更新できません:外部キー制約が失敗しました」というメッセージが表示されます。
Erin Geyer 2017年

2
「SET FOREIGN_KEY_CHECKS = 0;」を実行しないでください。「外部キー制約が失敗しました」というエラーが発生した場合は、明らかに修正が必要な不良データがあるか、そうでない場合はさらに大きな問題が発生します。
MazeChaZer

72

このクエリを使用するだけで、私のシナリオに従って試しましたが、うまく機能します

ALTER TABLE katalog ADD FOREIGN KEY (`Sprache`) REFERENCES Sprache(`ID`);


15

このリンクを確認してください。それはerrno 150で私を助けました:http : //verysimple.com/2006/10/22/mysql-error-number-1005-cant-create-table-mydbsql-328_45frm-errno-150/

私の頭の上には2つのことが頭に浮かびます。

  • 外部キーインデックスはデータベース全体で一意の名前ですか(リストの#3)?
  • 更新時にテーブルPKをNULLに設定しようとしていますか(リストの#5)?

私は、問題が更新時にNULLを設定することにあると思います(私の頭脳が、今日のように逆になっていない場合は...)。

編集:元の投稿のコメントを見逃しました。unsigned / not unsigned int列はおそらくあなたのケースを解決しました。私のリンクが将来の考えで誰かを助けることを願っています。


13
FOREIGN KEY (`Sprache`)
REFERENCES `Sprache` (`ID`)
ON DELETE SET NULL
ON UPDATE SET NULL;

しかし、あなたのテーブルは:

CREATE TABLE `katalog` (
`Sprache` int(11) NOT NULL,

それはカントそれはNOT NULLとして定義されているので、NULLに列Spracheを設定します。


5

MySQLはこのクエリを実行します。

ALTER TABLE `db`.`table1`
ADD COLUMN `col_table2_fk` INT UNSIGNED NULL,
ADD INDEX `col_table2_fk_idx` (`col_table2_fk` ASC),
ADD CONSTRAINT `col_table2_fk1`
FOREIGN KEY (`col_table2_fk`)
REFERENCES `db`.`table2` (`table2_id`)
ON DELETE NO ACTION
ON UPDATE NO ACTION;

乾杯!


5

直し方 Error Code: 1005. Can't create table 'mytable.#sql-7fb1_7d3a' (errno: 150) in mysql.

  1. テーブルを変更し、インデックスを追加します。

    ALTER TABLE users ADD INDEX index_name (index_column)
  2. 次に、制約を追加します

    ALTER TABLE foreign_key_table
    ADD CONSTRAINT foreign_key_name FOREIGN KEY (foreign_key_column)
    REFERENCES primary_key_table (primary_key_column) ON DELETE NO ACTION
    ON UPDATE CASCADE;

インデックスを追加しないと機能しません。

約6時間それと戦った後、私はこれが魂を救うことを望んでいる解決策を思いつきました。


4

ALTER TABLEを使用してテーブルに外部キー制約を追加するときは、最初に必要なインデックスを作成することを忘れないでください。

  1. インデックスを作成
  2. 他の机

両方のインデックスを作成しました。実行しようとすると、以前と同じエラーメッセージが表示されます。「更新時に削除」の部分を否認すると機能しますが、「削除時」のアクションが間違っています;)
frgtv10

@ frgtv10テーブルデータが「削除時」と競合する可能性が最も高い。
Maksym Polshcha

3

1つのクエリですべてを試す

  ALTER TABLE users ADD grade_id SMALLINT UNSIGNED NOT NULL DEFAULT 0,
      ADD CONSTRAINT fk_grade_id FOREIGN KEY (grade_id) REFERENCES grades(id);

0

これは基本的に、テーブルが2つの異なる文字セットにあるために発生します。例として、charset = utf-8で作成された1つのテーブルと他のテーブルはCHARSET = latin1で作成されているため、これらのテーブルに外部キーを追加できます。両方のテーブルで同じ文字セットを使用すると、外部キーを追加できます。誤って形成されたエラー1005 foriegnキー制約はこれから解決できます


0

私は同じ問題を乗り越えました。私の場合、テーブルには既にデータがあり、参照テーブルには存在しないキーがこのテーブルにありました。だから私は制約を無視し、すべてがうまくいったこの行を削除しなければなりませんでした。


0

ステップ1:このスクリプトを実行する

SET FOREIGN_KEY_CHECKS=0;

ステップ2:列を追加する

ALTER TABLE mileage_unit ADD COLUMN COMPANY_ID BIGINT(20) NOT NULL

ステップ3:追加した列に外部キーを追加する

ALTER TABLE mileage_unit
ADD FOREIGN KEY (COMPANY_ID) REFERENCES company_mst(COMPANY_ID);

ステップ4:このスクリプトを実行する

SET FOREIGN_KEY_CHECKS=1;

-1
 ALTER TABLE TABLENAME ADD FOREIGN KEY (Column Name) REFERENCES TableName(column name)

例:-

ALTER TABLE Department ADD FOREIGN KEY (EmployeeId) REFERENCES Employee(EmployeeId)

1
他の人がコードから学ぶことができるように、コードにいくつかの説明を追加してください
Nico Haase
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.