352

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

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

这是我用来创建表的 SQL,两个有问题的表是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;
4

25 回答 25

870

要查找特定错误,请运行以下命令:

SHOW ENGINE INNODB STATUS;

并查看该LATEST FOREIGN KEY ERROR部分。

子列的数据类型必须与父列完全匹配。例如,既然medicalhistory.MedicalHistoryID是一个INTPatient.MedicalHistory也需要是一个INT,而不是一个SMALLINT

此外,您应该set foreign_key_checks=0在运行 DDL 之前运行查询,这样您就可以按任意顺序创建表,而无需在相关子表之前创建所有父表。

于 2013-03-20T21:30:21.237 回答
160

我已将一个字段设置为“未签名”,而另一个则没有。一旦我将两列都设置为无符号,它就起作用了。

于 2015-02-12T06:21:28.423 回答
107
  • 引擎应该是相同的,例如 InnoDB
  • 数据类型应该相同,并且具有相同的长度。例如 VARCHAR(20)
  • Collat​​ion Columns 字符集应该相同。例如 utf8
    Watchout:即使您的表有相同的排序规则,列仍然可能有不同的排序规则。
  • 唯一- 外键应指引用表中唯一的字段(通常是主键)
于 2016-01-22T17:59:56.743 回答
23

尝试在外键 - smallint(5) - 上使用相同类型的主键 - int(11)

希望能帮助到你!

于 2013-03-20T21:34:45.480 回答
16

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

在我自己的情况下,其中一张表正在使用utf8,另一张正在使用latin1.

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

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

ALTER TABLE tablename CONVERT TO CHARACTER SET utf8 COLLATE utf8_unicode_ci;

我希望这可以帮助别人。

于 2016-06-29T12:07:56.307 回答
8

要在表 B 中设置 FOREIGN KEY,您必须在表 A 中设置 KEY。

在表 A 中:索引id( id)

然后在表 B 中,

CONSTRAINT `FK_id` FOREIGN KEY (`id`) REFERENCES `table-A` (`id`)
于 2014-06-04T12:49:00.067 回答
8

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

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

于 2015-03-04T23:53:47.420 回答
4

检查以下规则:

  • 首先检查是否为表名赋予了正确的名称

  • 第二个正确的数据类型给外键?

于 2013-11-20T19:05:12.537 回答
4

请确保这两个表都是 InnoDB 格式。即使是 MyISAM 格式,外键约束也不起作用。

另外,另一件事是,两个字段应该是相同的类型。如果一个是 INT,那么另一个也应该是 INT。如果一个是 VARCHAR,另一个也应该是 VARCHAR,等等。

于 2015-07-02T11:30:44.463 回答
3

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

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

于 2016-02-29T05:36:05.730 回答
3

检查两个表格列上的签名。如果引用表列已签名,则引用表列也应签名。

于 2016-11-23T08:34:24.710 回答
3

我的问题是我试图在其他表之前创建关系表!

所以你有两种方法可以解决它:

  • 更改 MSQL 命令的顺序

  • 在您的查询之前运行它:

    SET foreign_key_checks = 0;

于 2019-05-11T07:15:25.177 回答
2

注意:下表是在我对数据库进行一些研发时从某个站点获取的。所以命名约定是不合适的。

对我来说,问题是,我的父表的字符集与我创建的表不同。

父表(产品)

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 
于 2018-10-12T19:15:54.130 回答
1

此错误的另一个原因是您的表或列包含保留关键字

有时确实会忘记这些。

于 2018-01-07T12:49:11.320 回答
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
);
于 2014-04-15T08:09:20.903 回答
0

我对不同表的两个外键有类似的错误,但键名相同!我已经重命名了键并且错误消失了)

于 2014-12-08T19:35:50.893 回答
0

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

以防万一它对任何人都有帮助

于 2015-02-28T12:09:13.613 回答
0

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

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

原因是:由于我使用 phpmyadmin 在重命名的数据库中创建了一些外键 - 使用数据库名称前缀创建的外键但未更新数据库名称前缀。所以备份数据库中仍然有指向新创建的数据库的引用。

于 2015-12-22T11:08:17.833 回答
0

我的解决方案可能有点尴尬,它讲述了为什么有时应该看看你面前的东西而不是这些帖子:)

我之前运行过一个正向工程师,但失败了,这意味着我的数据库已经有几个表,然后我一直在尝试修复外键约束失败,试图确保一切都很完美,但它遇到了以前创建的表,所以它没有占上风。

于 2016-08-16T16:30:43.507 回答
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

REFERENCES我必须在和之间留一个空格role才能让它工作。

于 2018-09-29T22:04:12.777 回答
0

对我来说,如果为引用当前数据库的非当前数据库创建 FK,则不能省略为当前数据库表添加前缀:

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

如果我省略“current_db”。对于用户表,我收到 FK 错误。有趣的是 SHOW ENGINE INNODB STATUS;在这种情况下没有显示任何内容。

于 2020-02-21T13:03:34.000 回答
0

我的解决方案!!

如果我们想让 table1 的 column1 作为 table2 的外键,那么 column1 应该是 table1 的键。

例如,考虑我们有一个departments表,它有dept_id列。

现在假设我们有另一个名为的表employees,其中包含emp_dept_id列。

如果我们想使用表的dept_id列作为 的列department的外键,那么表的列应该至少是一个键,如果不是主键的话。emp_dept_idempdept_iddepartment

因此,在将其用作另一个表的外键之前,请确保它dept_id是主键或唯一键。depratment

于 2021-07-22T04:56:47.403 回答
0

如果您在使用 PhpMyAdmin 时遇到此错误,请在导入 SQL 文件之前禁用外键检查。

在此处输入图像描述

于 2021-08-25T09:59:20.693 回答
0

对我来说,目标表阻止了外键。AI我必须在外键指向的表上设置 Auto-Increment ( )。

于 2022-03-02T12:45:34.353 回答
-1

我遇到了同样的问题,然后我在父表和子表中将引擎名称更正为 Innodb,并更正了引用字段名称 FOREIGN KEY ( c_id) REFERENCES x9o_parent_table( c_id)
,然后它工作正常并且表安装正确。这将对某人完全使用。

于 2015-10-14T10:18:43.700 回答