MySQL Не Может Добавить Ограничение Внешнего Ключа

поэтому я пытаюсь добавить ограничения внешнего ключа в свою базу данных в качестве требования проекта, и он работал в первый раз или два в разных таблицах, но у меня есть две таблицы, в которых я получаю ошибку при попытке добавить ограничения внешнего ключа. Сообщение об ошибке, которое я получаю:

ошибка 1215 (HY000): не удается добавить ограничение внешнего ключа

это 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;

19 ответов


, чтобы найти конкретную ошибку так:

SHOW ENGINE INNODB STATUS;

и посмотрите в .

тип данных для дочернего столбца должен точно соответствовать родительскому столбцу. Например, с medicalhistory.MedicalHistoryID это INT, Patient.MedicalHistory должен быть INT, а не SMALLINT.

кроме того, вы должны запустить запрос set foreign_key_checks=0 перед запуском DDL, чтобы вы могли создавать таблицы в произвольном порядке, а не создавать все родительские таблицы перед соответствующим дочерняя таблица.


Я установил одно поле как "Unsigned", а другое-нет. Как только я установил оба столбца в Unsigned, это сработало.


  • двигатель надо же например InnoDB
  • тип должно быть таким же, и с такой же длиной. например, VARCHAR (20)
  • сортировка кодировка столбцов должна быть одинаковой. напр. utf8
    Watchout: даже если ваши таблицы имеют одинаковые параметры сортировки, столбцы все равно могут иметь разные.
  • уникальный - внешний ключ должен обратитесь к уникальному полю (обычно это первичный ключ) в справочной таблице.

попробуйте использовать тот же тип первичные ключи - int (11) - на внешних ключах -smallint (5) - Как хорошо.

надеюсь, что это помогает!


убедитесь, что кодировка символов и параметры сортировки для двух таблиц одинаковы.

в моем случае одна из таблиц использовала utf8 а другой использовал latin1.

у меня был другой случай, когда кодировка была такой же, но сопоставление разных. Один utf8_general_ci другое utf8_unicode_ci

вы можете запустить эту команду, чтобы установить кодировку и параметры сортировки для таблицы.

ALTER TABLE tablename CONVERT TO CHARACTER SET utf8 COLLATE utf8_unicode_ci;

надеюсь, это кому-то поможет.


чтобы установить внешний ключ в таблице B, вы должны установить ключ в таблице A.

в таблице A: Индекс id (id)

и затем в таблице B,

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

пожалуйста, убедитесь, что обе таблицы находятся в формате InnoDB. Даже если он находится в формате MyISAM, ограничение внешнего ключа не будет работать.

кроме того, другое дело, что оба поля должны иметь одинаковый тип. Если один INT, то другой также должен быть INT. Если один из них VARCHAR, другой также должен быть VARCHAR и т. д.


проверьте следующие правила :

  • сначала проверяет, указаны ли имена для имен таблиц

  • второй правый тип данных дает внешний ключ ?


У меня была такая же проблема и решение оказалось очень простым. Решение: внешние ключи, объявленные в таблице, не должны иметь значение not null.

ссылка: Если вы задаете действие SET NULL, убедитесь, что вы не объявили столбцы в дочерней таблице как NOT NULL. (ref )


Я столкнулся с проблемой и смог ее решить, убедившись, что типы данных точно совпадают .

Я использовал SequelPro для добавления ограничения, и он делал первичный ключ как неподписанный по умолчанию .


У меня была аналогичная ошибка при создании внешнего ключа в таблице "многие ко многим", где первичный ключ состоял из 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
);

У меня была аналогичная ошибка с двумя внешними ключами для разных таблиц, но с одинаковым ключом именами! Я переименовал ключи, и ошибка ушла)


была аналогичная ошибка, но в моем случае мне не хватало объявить pk как auto_increment.

на всякий случай это может быть полезно, чтобы кто-нибудь


Я получил ту же ошибку. Причиной в моем случае было:

  1. Я создал резервную копию базы данных через phpmyadmin, скопировав всю базу данных.
  2. Я создал новую БД с тем же именем, что и старая БД, и выбрал ее.
  3. я запустил сценарий SQL для создания обновленных таблиц и данных.
  4. я получил ошибку. Кроме того, когда я отключил foreign_key_checks. Хотя база данных была совершенно пуста.

причина была: с phpmyadmin для создания некоторых внешних ключей в переименованной базе данных-внешние ключи, где создан с префиксом имени базы данных, но префикс имени базы данных не был обновлен. Таким образом, в резервной копии все еще были ссылки, указывающие на вновь созданную БД.


мое решение, возможно, немного смущает и рассказывает историю о том, почему вы иногда должны смотреть на то, что у вас есть перед вами вместо этих сообщений :)

раньше я запускал передового инженера, который потерпел неудачу, так что это означало, что в моей базе данных уже было несколько таблиц, тогда я сидел, пытаясь исправить ошибки контрейнтов внешнего ключа, пытаясь убедиться, что все идеально, но он столкнулся с ранее созданными таблицами, поэтому он не превалировал.


Проверьте подпись на обоих столбцах таблицы. Если столбец ссылочной таблицы подписан, то должен быть подписан и столбец ссылочной таблицы.


одной из дополнительных причин этой ошибки является то, что ваши таблицы или столбцы содержат зарезервированные ключевые слова:

иногда об этом забывают.


в моем случае была синтаксическая ошибка, которая не была явно уведомлена консолью MySQL при запуске запроса. Однако,SHOW ENGINE INNODB STATUS команды сообщал

  Syntax error close to:

  REFERENCES`role`(`id`) ON DELETE CASCADE) ENGINE = InnoDB DEFAULT CHARSET = utf8

мне пришлось оставить пробел между REFERENCES и role чтобы заставить его работать.


у меня была эта же проблема, затем я исправил имя двигателя как Innodb в родительской и дочерней таблицах и исправил имя ссылочного поля ВНЕШНИЙ КЛЮЧ (c_id) ссылки x9o_parent_table(c_id)
затем он работает нормально, и таблицы установлены правильно. Это будет использовать полный для кого-то.