MySQL не может добавить ограничение внешнего ключа

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

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

Это SQL, который я использую для создания таблиц, для двух таблиц: Patient и Appointment.

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;

Ответ 1

Чтобы найти конкретную ошибку, выполните следующее:

SHOW ENGINE INNODB STATUS;

И посмотрите в разделе LATEST FOREIGN KEY ERROR.

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

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

Ответ 2

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

Ответ 3

  • Двигатель должен быть таким же, например. InnoDB
  • Тип данных должен совпадать с той же длиной. например VARCHAR (20)
  • Collation Колонка символов должна быть одинаковой. например utf8
    Watchout: Даже если ваши таблицы имеют одинаковое значение Collation, столбцы могут быть разными.
  • Уникальный. Внешний ключ должен ссылаться на поле, которое является уникальным (обычно первичный ключ) в справочной таблице.

Ответ 4

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

Надеюсь, что это поможет!

Ответ 5

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

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

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

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

ALTER TABLE tablename CONVERT TO CHARACTER SET utf8 COLLATE utf8_unicode_ci;

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

Ответ 6

Чтобы установить FOREIGN KEY в таблице B, вы должны установить KEY в таблице A.

В таблице A:   INDEX id (id)

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

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

Ответ 7

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

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

Ответ 8

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

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

Ответ 9

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

  • Сначала проверяется правильность присвоения имен именам таблиц

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

Ответ 10

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

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

Ответ 11

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

Ответ 12

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

Ответ 13

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

Ответ 14

Имел подобную ошибку, но в моем случае я отсутствовал, чтобы объявить pk как auto_increment.

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

Ответ 15

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

  • Я создал резервную копию базы данных через phpmyadmin, скопировав всю базу данных.
  • Я создал новый db с тем же именем, что и старый db, и выбрал его.
  • Я создал SQL script для создания обновленных таблиц и данных.
  • Я получил ошибку. Также, когда я отключил foreign_key_checks. Хотя база данных была полностью пустой.

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

Ответ 16

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

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

Ответ 17

Еще одна причина этой ошибки - когда ваши таблицы или столбцы содержат зарезервированные ключевые слова:

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

Ответ 18

В моем случае, была синтаксическая ошибка, которая не была явно уведомлена консолью 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 чтобы все заработало.

Ответ 19

ПРИМЕЧАНИЕ. Следующие таблицы были взяты с какого-то сайта, когда я занимался исследованиями в базе данных. Таким образом, соглашение об именах не является правильным.

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

Родительский стол (ПРОДУКТЫ)

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 

Ответ 20

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

Ответ 21

У меня была такая же проблема, после чего я исправил имя Engine как Innodb в родительских и дочерних таблицах и исправил имя ссылочного поля ИНОСТРАННЫЙ КЛЮЧ (c_id) ССЫЛКИ x9o_parent_table (c_id)
то он отлично работает, и таблицы установлены правильно. Это будет полезно для кого-то.