2013-03-20 6 views
181

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

ERROR 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; 

ответ

495

Чтобы найти конкретный прогон ошибки это:

SHOW ENGINE INNODB STATUS; 

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

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

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

+1

Спасибо, как несоответствие типа данных, так и foreign_key_checks исправили проблему! – joshuaegclark

+12

Был вызван другой сортировкой на таблицах для меня, один был UTF-8, а другой был latin1. –

+0

Я запускал set foreign_key_checks = 0, но я все еще получаю ошибку из-за произвольного порядка таблиц :( – JoeTidee

14

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

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

+0

mysql> создать уникальный индекс index_bar_id на foos (bar_id); ... mysql> alter table foos добавить ограничение index_bar_id внешний ключ (bar_id) reference bars (id); http://sixarm.com/about/mysql-create-indexes-foreign-keys-constraints.html – CookieCoder

3

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

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

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

0

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

Чтобы установить FOREIGN KEY в таблице B необходимо установить ключ в таблице А.

в таблице А: INDEX id (id)

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

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

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

88

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

+2

Настройка для 'unsigned' также работала для меня. – timothymarois

+0

Настройка неподписанного поля для внешнего ключа работала для меня – manian

0

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

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

3

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

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

4

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

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

-1

У меня была такая же проблема, то я исправил название двигателя, как Innodb в обоих родительских и дочерних таблиц и исправил имя ссылки поля FOREIGN KEY (c_id) ЛИТЕРАТУРЫ x9o_parent_table (c_id)
тогда он отлично работает, и таблицы установлены правильно. Это будет полезно для кого-то.

0

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

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

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

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

Лучший ответ Когда-либо, попробовав почти все, оказалось, что я должен явно добавить «уникальный» в столбец ссылочной таблицы, даже если это «Первичный ключ» !! – Yahya

1

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

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

9

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

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

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

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

ALTER TABLE tablename CONVERT TO CHARACTER SET utf8 COLLATE utf8_unicode_ci; 

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

+0

Nice one @Adegoke, отличный ответ –

0

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

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

0

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

0

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

Иногда один делает забыть это.