MySQL Cannot Add Foreign Key Constraint
因此,我正试图将外键约束作为一个项目需求添加到我的数据库中,它第一次或两次在不同的表上工作,但是我有两个表,当试图添加外键约束时,在这两个表上会出现错误。我得到的错误消息是:
ERROR 1215 (HY000): Cannot add foreign key constraint
这是我用来创建表的SQL,两个有问题的表是
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 | 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; |
要查找特定错误,请运行以下命令:
看一下
子列的数据类型必须与父列完全匹配。例如,由于
另外,您应该在运行DDL之前运行查询
我设置了一个字段为"unsigned",而另一个字段不是。一旦我将这两列都设置为无符号,它就工作了。
- 发动机应相同,例如InnoDB
- 数据类型应相同,且长度相同。例如varchar(20)
- 排序规则列的字符集应相同。例如UTF8注意:即使您的表具有相同的排序规则,列也可能具有不同的排序规则。
- 唯一-外键应引用引用引用表中唯一(通常是主键)的字段。
尝试在外键上使用相同类型的主键-int(11)-smallint(5)-以及。
希望它有帮助!
确认两个表的字符编码和排序规则相同。
在我自己的例子中,其中一个表使用
我有另一个例子,编码相同,但排序规则不同。一个是
可以运行此命令来设置表的编码和排序规则。
我希望这能帮助别人。
要在表B中设置外键,必须在表A中设置一个键。
表A:指数
然后在B表中,
1 |
我也有同样的问题,解决方法很简单。解决方案:表中声明的外键不应设置为非空。
引用:如果指定了set null操作,请确保没有将子表中的列声明为not null。(参考文献))
请确保这两个表都是InnoDB格式。即使其中一个是myisam格式,那么,外键约束也不会起作用。
另外,另一件事是,两个字段的类型应该相同。如果一个是int,那么另一个也应该是int。如果一个是varchar,另一个也应该是varchar等。
检查以下规则:
首先检查是否为表名赋予了正确的名称
第二个正确的数据类型给了外键?
我面临着这个问题,并且能够通过确保数据类型完全匹配来解决它。
我使用Sequelpro来添加约束,它使主键默认为无符号。
检查两个表列上的签名。如果引用表列已签名,则引用表列也应签名。
我也犯了同样的错误。在我的案例中,原因是:
原因是:因为我使用phpmyadmin在重命名的数据库中创建了一些外键-使用数据库名称前缀创建但未更新数据库名称前缀的外键。所以备份数据库中仍然有指向新创建的数据库的引用。
NOTE: The following tables were taken from some site when I was doing
some R&D on the database. So the naming convention is not proper.
对我来说,问题是,我的父表的字符集与我创建的父表的字符集不同。
父表(产品)
1 2 3 4 5 6 7 8 9 10 11 12 13 14 | 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 |
有问题的子表(价格日志)
1 2 3 4 5 6 7 8 9 10 | 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 ); |
修改为
1 2 3 4 5 6 7 8 9 10 | 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 |
我的解决方案可能有点尴尬,并讲述了为什么有时候你应该看看你面前的东西而不是这些帖子:)
我以前曾运行过一个转发工程师,但失败了,这意味着我的数据库已经有几个表了,然后我一直坐在那里试图修复外键约束失败,试图确保一切都是完美的,但它与以前创建的表不符,所以它无法获胜。
有一个类似的错误,但在我的例子中,我没有声明pk为自动增量。
以防对任何人都有帮助
对于不同的表,但具有相同的键名的两个外键,我也有类似的错误!我已重命名密钥,错误已消失)
此错误的另一个原因是当表或列包含保留关键字时:
有时人们会忘记这些。
在多对多表中创建外键时,我也遇到了类似的错误,其中主键由2个外键和另一个普通列组成。我通过更正引用的表名即公司来解决问题,如下面更正的代码所示:
1 2 3 4 5 6 7 8 9 10 11 12 13 | 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 ); |
在我的例子中,有一个语法错误,MySQL控制台在运行查询时没有明确通知它。但是,
1 2 3 |
我不得不在
我有同样的问题,然后在父表和子表中更正了与innodb相同的引擎名,并更正了引用字段名。外键(