web-dev-qa-db-ja.com

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

だから私はプロジェクトの要件として私のデータベースに外部キー制約を追加しようとしていて、それは異なるテーブルで初めてまたは2つはたらきましたが、外部キー制約を追加しようとするとエラーになる2つのテーブルがあります。私が得るエラーメッセージは次のとおりです。

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

これは私がテーブルを作成するために使用しているSQLです、2つの問題のあるテーブルはPatientAppointmentです。

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;
258
joshuaegclark

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

SHOW ENGINE INNODB STATUS;

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

子列のデータ型は、親列と正確に一致する必要があります。たとえば、medicalhistory.MedicalHistoryIDINTなので、Patient.MedicalHistoryINTではなくSMALLINTである必要があります。

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

649
Ike Walker

1つのフィールドを "符号なし"に設定し、他のフィールドを "符号なし"に設定しました。両方のカラムをUnsignedに設定するとうまくいきました。

125
  • エンジン は同じでなければなりませんInnoDB
  • データ型 は同じ長さである必要があります。 例VARCHAR(20)
  • 照合順序 列の文字セットは同じである必要があります。 例utf8
    Watchout:テーブルの照合順序が同じでも、列の照合順序が異なる可能性があります。
  • Unique - 外部キーは、参照テーブル内で一意の(通常は主キー)であるフィールドを参照する必要があります。
63
Andrew

同じ種類の主キーを使用してみます - int(11) - 外部キーについて - smallint(5) - 同様に。

それが役に立てば幸い!

15
Felypp Oliveira

2つの表の文字エンコードと照合が同じであることを確認してください。

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

エンコードは同じだが照合順序が異なるという別のケースがありました。片方のutf8_general_ci、もう片方のutf8_unicode_ci

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

ALTER TABLE tablename CONVERT TO CHARACTER SET utf8 COLLATE utf8_unicode_ci;

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

11
Goke Obasa

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

テーブルAの場合:INDEX idid

そして表Bでは、

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

私は同じ問題を抱えており、解決策は非常に単純でした。解決策:tableで宣言されている外部キーをnull以外に設定しないでください。

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

5
Singh

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

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

4
Vijay Srinivas

以下の規則を確認してください。

  • 最初にテーブル名に対して名前が正しいかどうかをチェックします

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

3
Bhaskar Bhatt

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

制約を追加するためにSequelProを使用していましたが、デフォルトでは主キーを符号なしにしていました。

2
Learner

両方のテーブル列の署名を確認してください。参照テーブルの列がSIGNEDの場合、参照テーブルの列もSIGNEDになります。

1
katwekibs

私の問題は、私が他のテーブルの前にリレーションテーブルを作成しようとしていたということでした!

0
Ahmad Mobaraki

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

時々人はこれらを忘れます。

0
EssGee

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

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
iltaf khalid

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

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

親テーブル(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つの外部キーで同じキー名を使っても同じようなエラーが発生しました。キーの名前を変更しましたが、エラーはなくなりました。

私は同じエラーを受けました。私の場合の原因は次のとおりです。

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

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

0
lsblsb

同様のエラーがありましたが、私の場合、pkをauto_incrementとして宣言することができませんでした。

万が一のためにそれがだれでもに役立つかもしれない

0
Luiz Rolim

私の解決策は多少恥ずかしいかもしれませんし、なぜあなたは時々これらの記事の代わりにあなたの前に持っているものを見るべきなのかという物語を伝えます:)

私はデータベースにいくつかのテーブルがあることを意味していました。それから私はすべてが完璧であることを確かめるために外部キーの制約の失敗を修正しようとして座っていました。以前に作成されたテーブルなので、普及することはありませんでした。

0
DenLilleMand

私の場合は、クエリを実行しても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
vicke4