it-roy-ru.com

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;
237
joshuaegclark

Чтобы найти конкретную ошибку, запустите это:

SHOW ENGINE INNODB STATUS;

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

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

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

619
Ike Walker

Я установил одно поле как «Без знака», а другое - нет. Как только я установил для обоих столбцов значение Без знака, это сработало.

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

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

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

15
Felypp Oliveira

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

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

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

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

ALTER TABLE tablename CONVERT TO CHARACTER SET utf8 COLLATE utf8_unicode_ci;

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

11
Goke Obasa

Чтобы установить ИНОСТРАННЫЙ КЛЮЧ в таблице B, вы должны установить КЛЮЧ в таблице A.

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

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

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

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

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

5
Singh

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

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

4
Vijay Srinivas

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

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

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

3
Bhaskar Bhatt

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

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

2
Learner

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

1
katwekibs

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

0
Ahmad Mobaraki

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

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

0
EssGee

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

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

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

Родительская таблица (ПРОДУКТЫ)

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 
0
Channaveer Hakari

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

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

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

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

0
lsblsb

Была похожая ошибка, но в моем случае я пропустил объявление pk как auto_increment.

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

0
Luiz Rolim

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

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

0
DenLilleMand

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

0
vicke4