MySQLは外部キー制約を追加できません


314

したがって、プロジェクトの要件としてデータベースに外部キー制約を追加しようとしていますが、最初または2回は異なるテーブルで機能しましたが、外部キー制約を追加しようとするとエラーが発生するテーブルが2つあります。表示されるエラーメッセージは次のとおりです。

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

これは、テーブルの作成に使用しているSQLです。問題のある2つのテーブルはPatientおよびAppointmentです。

SET @OLD_UNIQUE_CHECKS=@@UNIQUE_CHECKS, UNIQUE_CHECKS=0;
SET @OLD_FOREIGN_KEY_CHECKS=@@FOREIGN_KEY_CHECKS, FOREIGN_KEY_CHECKS=1;
SET @OLD_SQL_MODE=@@SQL_MODE, SQL_MODE='TRADITIONAL,ALLOW_INVALID_DATES';

CREATE SCHEMA IF NOT EXISTS `doctorsoffice` DEFAULT CHARACTER SET utf8 ;
USE `doctorsoffice` ;

-- -----------------------------------------------------
-- Table `doctorsoffice`.`doctor`
-- -----------------------------------------------------
DROP TABLE IF EXISTS `doctorsoffice`.`doctor` ;

CREATE  TABLE IF NOT EXISTS `doctorsoffice`.`doctor` (
  `DoctorID` INT(11) NOT NULL AUTO_INCREMENT ,
  `FName` VARCHAR(20) NULL DEFAULT NULL ,
  `LName` VARCHAR(20) NULL DEFAULT NULL ,
  `Gender` VARCHAR(1) NULL DEFAULT NULL ,
  `Specialty` VARCHAR(40) NOT NULL DEFAULT 'General Practitioner' ,
  UNIQUE INDEX `DoctorID` (`DoctorID` ASC) ,
  PRIMARY KEY (`DoctorID`) )
ENGINE = InnoDB
DEFAULT CHARACTER SET = utf8;


-- -----------------------------------------------------
-- Table `doctorsoffice`.`medicalhistory`
-- -----------------------------------------------------
DROP TABLE IF EXISTS `doctorsoffice`.`medicalhistory` ;

CREATE  TABLE IF NOT EXISTS `doctorsoffice`.`medicalhistory` (
  `MedicalHistoryID` INT(11) NOT NULL AUTO_INCREMENT ,
  `Allergies` TEXT NULL DEFAULT NULL ,
  `Medications` TEXT NULL DEFAULT NULL ,
  `ExistingConditions` TEXT NULL DEFAULT NULL ,
  `Misc` TEXT NULL DEFAULT NULL ,
  UNIQUE INDEX `MedicalHistoryID` (`MedicalHistoryID` ASC) ,
  PRIMARY KEY (`MedicalHistoryID`) )
ENGINE = InnoDB
DEFAULT CHARACTER SET = utf8;


-- -----------------------------------------------------
-- Table `doctorsoffice`.`Patient`
-- -----------------------------------------------------
DROP TABLE IF EXISTS `doctorsoffice`.`Patient` ;

CREATE  TABLE IF NOT EXISTS `doctorsoffice`.`Patient` (
  `PatientID` INT unsigned NOT NULL AUTO_INCREMENT ,
  `FName` VARCHAR(30) NULL ,
  `LName` VARCHAR(45) NULL ,
  `Gender` CHAR NULL ,
  `DOB` DATE NULL ,
  `SSN` DOUBLE NULL ,
  `MedicalHistory` smallint(5) unsigned NOT NULL,
  `PrimaryPhysician` smallint(5) unsigned NOT NULL,
  PRIMARY KEY (`PatientID`) ,
  UNIQUE INDEX `PatientID_UNIQUE` (`PatientID` ASC) ,
  CONSTRAINT `FK_MedicalHistory`
    FOREIGN KEY (`MEdicalHistory` )
    REFERENCES `doctorsoffice`.`medicalhistory` (`MedicalHistoryID` )
    ON DELETE CASCADE
    ON UPDATE CASCADE,
  CONSTRAINT `FK_PrimaryPhysician`
    FOREIGN KEY (`PrimaryPhysician` )
    REFERENCES `doctorsoffice`.`doctor` (`DoctorID` )
    ON DELETE CASCADE
    ON UPDATE CASCADE)
ENGINE = InnoDB;


-- -----------------------------------------------------
-- Table `doctorsoffice`.`Appointment`
-- -----------------------------------------------------
DROP TABLE IF EXISTS `doctorsoffice`.`Appointment` ;

CREATE  TABLE IF NOT EXISTS `doctorsoffice`.`Appointment` (
  `AppointmentID` smallint(5) unsigned NOT NULL AUTO_INCREMENT ,
  `Date` DATE NULL ,
  `Time` TIME NULL ,
  `Patient` smallint(5) unsigned NOT NULL,
  `Doctor` smallint(5) unsigned NOT NULL,
  PRIMARY KEY (`AppointmentID`) ,
  UNIQUE INDEX `AppointmentID_UNIQUE` (`AppointmentID` ASC) ,
  CONSTRAINT `FK_Patient`
    FOREIGN KEY (`Patient` )
    REFERENCES `doctorsoffice`.`Patient` (`PatientID` )
    ON DELETE CASCADE
    ON UPDATE CASCADE,
  CONSTRAINT `FK_Doctor`
    FOREIGN KEY (`Doctor` )
    REFERENCES `doctorsoffice`.`doctor` (`DoctorID` )
    ON DELETE CASCADE
    ON UPDATE CASCADE)
ENGINE = InnoDB;


-- -----------------------------------------------------
-- Table `doctorsoffice`.`InsuranceCompany`
-- -----------------------------------------------------
DROP TABLE IF EXISTS `doctorsoffice`.`InsuranceCompany` ;

CREATE  TABLE IF NOT EXISTS `doctorsoffice`.`InsuranceCompany` (
  `InsuranceID` smallint(5) NOT NULL AUTO_INCREMENT ,
  `Name` VARCHAR(50) NULL ,
  `Phone` DOUBLE NULL ,
  PRIMARY KEY (`InsuranceID`) ,
  UNIQUE INDEX `InsuranceID_UNIQUE` (`InsuranceID` ASC) )
ENGINE = InnoDB;


-- -----------------------------------------------------
-- Table `doctorsoffice`.`PatientInsurance`
-- -----------------------------------------------------
DROP TABLE IF EXISTS `doctorsoffice`.`PatientInsurance` ;

CREATE  TABLE IF NOT EXISTS `doctorsoffice`.`PatientInsurance` (
  `PolicyHolder` smallint(5) NOT NULL ,
  `InsuranceCompany` smallint(5) NOT NULL ,
  `CoPay` INT NOT NULL DEFAULT 5 ,
  `PolicyNumber` smallint(5) NOT NULL AUTO_INCREMENT ,
  PRIMARY KEY (`PolicyNumber`) ,
  UNIQUE INDEX `PolicyNumber_UNIQUE` (`PolicyNumber` ASC) ,
  CONSTRAINT `FK_PolicyHolder`
    FOREIGN KEY (`PolicyHolder` )
    REFERENCES `doctorsoffice`.`Patient` (`PatientID` )
    ON DELETE CASCADE
    ON UPDATE CASCADE,
  CONSTRAINT `FK_InsuranceCompany`
    FOREIGN KEY (`InsuranceCompany` )
    REFERENCES `doctorsoffice`.`InsuranceCompany` (`InsuranceID` )
    ON DELETE CASCADE
    ON UPDATE CASCADE)
ENGINE = InnoDB;

USE `doctorsoffice` ;


SET SQL_MODE=@OLD_SQL_MODE;
SET FOREIGN_KEY_CHECKS=@OLD_FOREIGN_KEY_CHECKS;
SET UNIQUE_CHECKS=@OLD_UNIQUE_CHECKS;

回答:


779

特定のエラーを見つけるには、次を実行します。

SHOW ENGINE INNODB STATUS;

そして、LATEST FOREIGN KEY ERRORセクションを見てください。

子列のデータ型は、親列と正確に一致する必要があります。たとえば、以来medicalhistory.MedicalHistoryIDINTPatient.MedicalHistoryまたにする必要があるINT、ありませんSMALLINT

また、set foreign_key_checks=0DDLを実行する前にクエリを実行して、関連する子テーブルの前にすべての親テーブルを作成する必要なく、任意の順序でテーブルを作成できるようにする必要があります。


3
おかげで、データ型の不整合とforeign_key_checksの両方で問題が修正されました!
joshuaegclark 2013年

30
テーブルの異なる照合順序が原因で発生しました。1つはUTF-8で、もう1つはlatin1でした。
ug_

6
タイプと長さが一致していても、これは符号なしINTだったので、「符号なし」をチェックしたことを確認する必要もありました。
timbrown

1
MyISAMエンジンでテーブルが自動的に作成されていました。イケありがとう。
キャプテンハイパーテキスト

3
ありがとう。set null削除しようとしましたが、列はでしたnot null
Matt

142

1つのフィールドを「署名なし」に設定し、他のフィールドはそうではありませんでした。両方の列を「署名なし」に設定すると、機能しました。


同じ笑 MySQLは、この種のものに対してより正確なエラー処理を使用できます。
デイブ

82
  • エンジンは同じである必要があります。例:InnoDB
  • データ型は同じで、長さが同じである必要があります。例:VARCHAR(20)
  • 照合列の文字セットは同じである必要があります。例:utf8
    監視:テーブルの照合順序が同じであっても、列の照合順序は異なる場合があります。
  • 一意 -外部キーは、参照テーブルで一意のフィールド(通常は主キー)を参照する必要があります。

1
これまでのベストアンサーほとんどすべてを試した後、それが!!でuniqueあっても、参照テーブルの列に明示的に追加する必要があることがわかりましたPrimary Key
Yahya

はい、これまでで最高の回答です...特に最初のモミ!私の場合、移行(2.5.14予約から2.7.2予約)を行いました。移行スクリプトはデータベースエンジンを変更しなかったため、新しいテーブルを作成するときにこのエラーが発生しました。
Bernhard

私もベストアンサーです。
EngineerCoder

チェック/変更の方法に関するヒントがあれば、さらに素晴らしいでしょう。(!アイデアに感謝)私にとっては、列レベルの照合順序の違いをした、これは私に修正与えた:stackoverflow.com/questions/1294117/...
sjgp

18

同じタイプの主キー(int(11))を外部キー(smallint(5))でも使用してみてください。

それが役に立てば幸い!


mysql> foos(bar_id);に一意のインデックスindex_bar_idを作成します。... mysql> alter table foos add constraint index_bar_id外部キー(bar_id)はバー(id)を参照します。 sixarm.com/about/…– CookieCoder 2013
16:09

11

2つのテーブルの文字エンコードと照合が同じであることを確認します。

私の場合、テーブルの1つがを使用utf8し、もう1つはを使用していましたlatin1

エンコーディングは同じだが照合順序が異なる別のケースがありました。一つのutf8_general_ci他のutf8_unicode_ci

このコマンドを実行して、テーブルのエンコードと照合を設定できます。

ALTER TABLE tablename CONVERT TO CHARACTER SET utf8 COLLATE utf8_unicode_ci;

これが誰かの役に立つことを願っています。


素敵な1つ@Adegoke、素晴らしい答え
エドウィンIkechukwu Okonkwo

7

テーブルBにFOREIGN KEYを設定するには、テーブルAにKEYを設定する必要があります。

テーブルA:INDEX idid

そして、テーブルBで、

CONSTRAINT `FK_id` FOREIGN KEY (`id`) REFERENCES `table-A` (`id`)

あなたが何を言っているのか正確にはわかりませんが、私の構文が間違っていることがわかりました。ALTER TABLEの航空機が制約fk_somehting_unique外部キー(OPERATOR_ID)参照組織を追加しますが、行っている必要があります:私はやっていたALTER TABLEの航空機は、制約fk_somehting_unique外部キー(OPERATOR_ID)参照組織の追加(id)を
Michael Coxon

7

同じ問題があり、解決策は非常に簡単でした。解決策:テーブルで宣言された外部キーをnullに設定しないでください。

参照:SET NULLアクションを指定する場合は、子テーブルの列をNOT NULLとして宣言していないことを確認してください。(参照


4

以下のルールを確認してください。

  • 最初に、名前がテーブル名に対して正しいかどうかを確認します

  • 2番目に正しいデータ型は外部キーに与えますか?


4

両方のテーブルがInnoDB形式であることを確認してください。MyISAM形式であっても、外部キー制約は機能しません。

また、もう1つは、両方のフィールドが同じタイプである必要があることです。一方がINTの場合、もう一方もINTである必要があります。一方がVARCHARの場合、もう一方もVARCHARなどにする必要があります。


3

私はこの問題に直面し、データ型が完全に一致することを確認することで解決できました。

制約を追加するためにSequelProを使用していて、デフォルトで主キーが署名されていませんでした。


2

テーブルの両方の列の署名を確認します。参照テーブル列がSIGNEDの場合、参照テーブル列もSIGNEDである必要があります。


1

注:次の表は、データベースの研究開発を行っているときに、あるサイトから取得したものです。したがって、命名規則は適切ではありません。

私にとっての問題は、私の親テーブルが私が作成していたものとは異なる文字セットを持っていることでした。

親テーブル(PRODUCTS)

products | CREATE TABLE `products` (
  `productCode` varchar(15) NOT NULL,
  `productName` varchar(70) NOT NULL,
  `productLine` varchar(50) NOT NULL,
  `productScale` varchar(10) NOT NULL,
  `productVendor` varchar(50) NOT NULL,
  `productDescription` text NOT NULL,
  `quantityInStock` smallint(6) NOT NULL,
  `buyPrice` decimal(10,2) NOT NULL,
  `msrp` decimal(10,2) NOT NULL,
  PRIMARY KEY (`productCode`),
  KEY `productLine` (`productLine`),
  CONSTRAINT `products_ibfk_1` FOREIGN KEY (`productLine`) REFERENCES `productlines` (`productLine`)
) ENGINE=InnoDB DEFAULT CHARSET=latin1

問題があった子テーブル(PRICE_LOGS)

price_logs | CREATE TABLE `price_logs` (
  `id` int(11) unsigned NOT NULL AUTO_INCREMENT,
  `productCode` varchar(15) DEFAULT NULL,
  `old_price` decimal(20,2) NOT NULL,
  `new_price` decimal(20,2) NOT NULL,
  `added_on` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP,
  PRIMARY KEY (`id`),
  KEY `productCode` (`productCode`),
  CONSTRAINT `price_logs_ibfk_1` FOREIGN KEY (`productCode`) REFERENCES `products` (`productCode`) ON DELETE CASCADE ON UPDATE CASCADE
);

に変更

price_logs | CREATE TABLE `price_logs` (
  `id` int(11) unsigned NOT NULL AUTO_INCREMENT,
  `productCode` varchar(15) DEFAULT NULL,
  `old_price` decimal(20,2) NOT NULL,
  `new_price` decimal(20,2) NOT NULL,
  `added_on` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP,
  PRIMARY KEY (`id`),
  KEY `productCode` (`productCode`),
  CONSTRAINT `price_logs_ibfk_1` FOREIGN KEY (`productCode`) REFERENCES `products` (`productCode`) ON DELETE CASCADE ON UPDATE CASCADE
) ENGINE=InnoDB DEFAULT CHARSET=latin1 


0

主キーが2つの外部キーと別の通常の列で構成される多対多テーブルで外部キーを作成するときに、同様のエラーが発生しました。以下の修正されたコードに示すように、参照されているテーブル名、つまり会社を修正することで問題を修正しました。

create table company_life_cycle__history -- (M-M)
(
company_life_cycle_id tinyint unsigned not null,
Foreign Key (company_life_cycle_id) references company_life_cycle(id) ON DELETE    CASCADE ON UPDATE CASCADE,
company_id MEDIUMINT unsigned not null,
Foreign Key (company_id) references company(id) ON DELETE CASCADE ON UPDATE CASCADE,
activity_on date NOT NULL,
PRIMARY KEY pk_company_life_cycle_history (company_life_cycle_id, company_id,activity_on),
created_on datetime DEFAULT NULL,
updated_on datetime DEFAULT NULL,
created_by varchar(50) DEFAULT NULL,
updated_by varchar(50) DEFAULT NULL
);

0

異なるテーブルの2つの外部キーで同様のエラーが発生しましたが、キー名は同じです!キーの名前を変更しましたが、エラーは発生していません)


0

同様のエラーがありましたが、私の場合、pkをauto_incrementとして宣言するのに欠けていました。

万が一に備えて


0

同じエラーが発生しました。私の場合の原因は:

  1. データベース全体をコピーして、phpmyadminでデータベースのバックアップを作成しました。
  2. 古いdbが選択した同じ名前の新しいdbを作成しました。
  3. 更新されたテーブルとデータを作成するSQLスクリプトを開始しました。
  4. エラーが発生しました。また、foreign_key_checksを無効にした場合。ただし、データベースは完全に空でした。

原因は次のとおりです。phpmyadminを使用して、名前が変更されたデータベースにいくつかの外部キーを作成したため、外部キーはデータベース名のプレフィックスで作成されましたが、データベース名のプレフィックスは更新されませんでした。そのため、新しく作成されたデータベースを指す参照がbackup-dbにまだありました。


0

私の解決策はおそらく少し恥ずかしいものであり、なぜこれらの投稿の代わりにあなたがあなたの前にあるものを時々見なければならないのかという話を伝えます:)

以前にフォワードエンジニアを実行したことがあり、失敗したため、データベースにはすでにいくつかのテーブルがあり、すべてが完璧であることを確認するために外部キー制約の失敗を修正しようとしていましたが、それはテーブルは以前に作成されたため、勝つことはできませんでした。


0

このエラーのもう1つの原因は、テーブルまたは列に予約済みキーワードが含まれている場合です。

時々これらを忘れます。


0

私の場合、クエリの実行時にMySQLコンソールから明示的に通知されない構文エラーがありました。しかし、SHOW ENGINE INNODB STATUSコマンドのLATEST FOREIGN KEY ERRORセクションは報告しました、

  Syntax error close to:

  REFERENCES`role`(`id`) ON DELETE CASCADE) ENGINE = InnoDB DEFAULT CHARSET = utf8

私は間の空白を残していたREFERENCESroleそれを動作させるために。


0

私にとってはそれでした-現在のDBを参照する現在ではないDBのFKを作成する場合、現在のDBテーブルのプレフィックスを省略することはできません。

USE currrent_db;
ALTER TABLE other_db.tasks ADD CONSTRAINT tasks_fk FOREIGN KEY (user_id) REFERENCES currrent_db.users (id);

「currrent_db」を省略した場合 usersテーブルの場合、FKエラーが発生します。SHOW ENGINE INNODB STATUS; この場合、何も表示されません。


-1

私はこれと同じ問題を抱えていたので、親テーブルと子テーブルの両方でエンジン名をInnodbに修正し、参照フィールド名FOREIGN KEY(c_id)REFERENCES x9o_parent_tablec_id)を修正したところ、
正常に機能し、テーブルが正しくインストールされました。これは誰かのために完全に使用されます。

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