MySQL不能添加外键约束
所以我试图将外键约束添加到我的数据库作为项目要求,它在不同的表上第一次或第二次工作,但我有两个表,当我试图添加外键约束时,我得到一个错误。 我得到的错误信息是:
错误1215(HY000):无法添加外键约束
这是我用来创build表的SQL,两个违规表是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;
要find具体的错误运行这个:
SHOW ENGINE INNODB STATUS;
并查看LATEST FOREIGN KEY ERROR
部分。
子列的数据types必须完全匹配父列。 例如,由于Patient.MedicalHistory
是一个INT
, Patient.MedicalHistory
也需要是一个INT
,而不是一个SMALLINT
。
另外,在运行DDL之前,您应该运行查询set foreign_key_checks=0
,以便您可以以任意顺序创build表,而不必在相关子表之前创build所有父表。
我把一个字段设置为“未签名”,另一个字段不是。 一旦我将两列设置为无符号,它的工作。
- 引擎应该是相同的, 例如InnoDB
- 数据types应该是相同的,并且具有相同的长度。 例如VARCHAR(20)
- 整理列字符集应该是相同的。 例如utf8
注意:即使你的表格有相同的整理,列仍然可以有不同的。 - 唯一 – 外键应引用参考表中唯一(通常是主键)的字段。
尝试使用相同types的主键 – int(11) – 在外键上 – smallint(5) – 。
希望能帮助到你!
确认两个表的字符编码和sorting规则是相同的。
在我自己的情况下,其中一个表使用utf8
,另一个表使用latin1
。
我有另外一个编码是相同的,但sorting不同的情况。 一个是utf8_general_ci
,另一个是utf8_unicode_ci
您可以运行此命令来设置表的编码和sorting规则。
ALTER TABLE tablename CONVERT TO CHARACTER SET utf8 COLLATE utf8_unicode_ci;
我希望这可以帮助别人。
请确保这两个表都是InnoDB格式。 即使有一个是MyISAM格式,那么外键约束也不起作用。
另外,还有一点是,这两个字段应该是相同的types。 如果一个是INT,那么另一个也应该是INT。 如果一个是VARCHAR,另一个也应该是VARCHAR等
要在表B中设置FOREIGN KEY,您必须在表A中设置一个KEY。
在表A中:INDEX id
( id
)
然后在表B中,
CONSTRAINT `FK_id` FOREIGN KEY (`id`) REFERENCES `table-A` (`id`)
检查以下规则:
-
首先检查名称是否给予正确的表名称
-
第二权利数据types给外键?
我有同样的问题,解决scheme非常简单。 解决scheme:在表中声明的外键不应该设置为非空。
参考:如果指定了SET NULL操作,请确保您没有将子表中的列声明为NOT NULL。 ( ref )
我有一个类似的错误,在主键由2个外键和另一个正常列组成的多对多表中创build外键。 我通过更正被引用的表名即公司来解决问题,如下面更正的代码所示:
create table company_life_cycle__history -- (MM) ( 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 );
我有两个外键不同的表,但具有相同的密钥名称类似的错误! 我已经重命名的键和错误已经消失)
有一个类似的错误,但在我的情况下,我错过了将pk声明为auto_increment。
以防万一它对任何人都有帮助
我得到了同样的错误。 我的原因是:
- 我通过复制整个数据库通过phpmyadmin创build了一个数据库的备份。
- 我创build了一个新的数据库,旧数据库有相同的名称和select它。
- 我启动了一个SQL脚本来创build更新的表和数据。
- 我得到了错误。 另外当我禁用foreign_key_checks。 尽pipe数据库完全是空的。
原因是:因为我使用phpmyadmin在重命名的数据库中创build一些外键 – 使用数据库名称前缀创build的外键,但数据库名称前缀没有更新。 所以在backup-db中还有一些引用指向新创build的数据库。
我遇到了这个问题,并通过确保数据types完全匹配来解决问题。
我使用SequelPro添加约束,并且默认情况下将主键设置为无符号。
我的解决scheme可能有点尴尬,并告诉你为什么有时应该看看你有什么在你面前而不是这些post的故事:)
之前我曾经经营过一名前程工程师,但是失败了,所以这意味着我的数据库已经有了几张表格,然后我一直在试图解决外键约束失败的问题,试图确保一切都是完美的,但是碰到了以前创build的表,所以没有占上风。
检查您的表格列上的签名。 如果引用表列是SIGNED,引用的表列也应该SIGNED。
我有这个相同的问题,然后我更正了引擎名称Innodb在父表和子表中,并更正了引用字段名称FOREIGN KEY( c_id
)REFERENCES x9o_parent_table
( c_id
)
那么它工作正常,表正确安装。 这将被充分用于某人。