2013-03-20 139 views
181

因此,我试图将外键约束添加到我的数据库作为项目要求,它在不同的表上第一次或第二次工作,但我有两个表,我得到一个错误时试图添加外键约束。 ,我得到的错误信息是:MySQL无法添加外键约束

ERROR 1215(HY000):无法添加外键约束

这是我用来创建表的SQL,这两个问题的表是PatientAppointment

SET @[email protected]@UNIQUE_CHECKS, UNIQUE_CHECKS=0; 
SET @[email protected]@FOREIGN_KEY_CHECKS, FOREIGN_KEY_CHECKS=1; 
SET @[email protected]@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 [email protected]_SQL_MODE; 
SET [email protected]_FOREIGN_KEY_CHECKS; 
SET [email protected]_UNIQUE_CHECKS; 

回答

495

要找到特定的错误运行此:

SHOW ENGINE INNODB STATUS; 

并期待在LATEST FOREIGN KEY ERROR部分。

子列的数据类型必须完全匹配父列。例如,由于medicalhistory.MedicalHistoryIDINT,Patient.MedicalHistory也需要是INT而不是SMALLINT

另外,在运行DDL之前,您应该运行查询set foreign_key_checks=0,以便您可以以任意顺序创建表,而不需要在相关子表之前创建所有父表。

+1

谢谢,数据类型不一致和foreign_key_checks修复了这个问题! – joshuaegclark 2013-03-20 21:53:29

+12

是由于我对表格的排序不同,一个是UTF-8,另一个是latin1。 – 2015-07-23 22:01:03

+0

我跑了集foreign_key_checks = 0,但我仍然得到错误,因为表的任意顺序:( – JoeTidee 2016-02-05 12:21:56

14

尝试使用相同类型的主键 - int(11) - 关于外键 - smallint(5) - 也是如此。

希望它有帮助!

+0

mysql>在foos上创建唯一索引index_bar_id(bar_id); ... mysql> alter table foos添加约束index_bar_id外键(bar_id)引用bars(id); http://sixarm.com/about/mysql-create-indexes-foreign-keys-constraints.html – CookieCoder 2013-12-17 16:09:16

3

检查以下规则:

  • 首先检查名是否给出正确的表名

  • 右二的数据类型给外键?

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 
); 
4

要设置一个外键表B必须在表A中设置关键

表A: INDEX idid

然后在表B,

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

我simil用两个外键为不同的表,但具有相同的键名称的错误!我已更名密钥和错误已经消失)

88

我已经设置了一个字段为“未签名”,而另一个没有。一旦我将两列设置为Unsigned,它就可以工作。

+2

设置为'unsigned'也适用于我。 – timothymarois 2017-02-16 14:35:12

+0

设置无符号的外键字段为我工作 – manian 2017-05-30 14:24:45

0

有一个类似的错误,但在我的情况下,我错过了将pk声明为auto_increment。

以防万一它可帮助任何人

3

我有同样的问题和解决方案是非常简单的。 解决方案:在表中声明的外键不应设置为非空。

参考:如果指定SET NULL操作,请确保您没有将子表中的列声明为NOT NULL。 (ref

4

请确保这两个表均采用InnoDB格式。即使其中一个是MyISAM格式,那么外键约束也不起作用。

此外,另一件事是,这两个领域应该是相同的类型。如果一个是INT,那么另一个也应该是INT。如果一个VARCHAR,其他的也应该是VARCHAR等

-1

我有同样的问题,那么我既父和子表中修正引擎名称InnoDB和修正的参考字段名 外键(c_id)参考x9o_parent_tablec_id
然后它工作正常,表正确安装。这将用于某人。

0

我得到了同样的错误。原因在我的情况是:

  1. 我通过复制整个数据库通过phpmyadmin创建了一个数据库的备份。
  2. 我创建了一个新的数据库,它具有与旧数据库相同的名称并选择了它。
  3. 我启动了一个SQL脚本来创建更新的表和数据。
  4. 我得到了错误。另外当我禁用foreign_key_checks。尽管数据库完全是空的。

的原因是:由于我用phpMyAdmin来创建在重命名的数据库的一些外键 - 在同一个数据库名称的前缀,但没有更新的数据库名称前缀创建的外键。所以在backup-db中仍然有引用指向新创建的数据库。

37
  • 引擎应该是相同的例如InnoDB
  • 数据类型应该是相同的,并且具有相同的长度。 例如VARCHAR(20)
  • 整理列字符集应该是相同的。 例如utf8
    注意:即使您的表格具有相同的整理,列仍可能有不同的整理。
  • 唯一 - 外键应该指参考表中唯一(通常是主键)的字段。
+1

最佳答案在尝试几乎所有事情后,事实证明,我必须明确地添加'唯一'到参考表列,即使它是一个'主键'! – Yahya 2017-11-14 11:18:11

1

我遇到了问题,并能够通过确保数据类型完全匹配来解决它。

我正在使用SequelPro添加约束,并且默认情况下将主键设置为无符号。

9

确认两个表的字符编码和排序规则是相同的。

在我自己的案例中,其中一个表使用的是utf8,另一个使用的是latin1

我有另一种情况,编码是相同的,但排序规则不同。一个utf8_general_ci另一个utf8_unicode_ci

您可以运行此命令来设置表的编码和排序规则。

ALTER TABLE tablename CONVERT TO CHARACTER SET utf8 COLLATE utf8_unicode_ci; 

我希望这可以帮助别人。

+0

不错的@Adegoke,很好的答案 – 2016-06-30 16:57:21

0

我的解决方案也许有点尴尬,并告诉你为什么应该有时候看你有你的,而不是这些职位:)

我以前跑了正向工程,其中未能面前你的故事,所以这意味着我的数据库已经有了几张表格,然后我一直在试图解决外键约束失败的问题,试图确保一切都是完美的,但是它在先前创建的表格上运行,所以它没有成功。

0

检查您的表格列上的签名。如果引用表列是SIGNED,则引用的表列也应该SIGNED。这个错误的

0

另外一个原因是,当你的表或列包含保留keywords

有时一个不忘记这些。