2013-03-20 132 views
181

因此,我試圖將外鍵約束添加到我的數據庫作爲項目要求,它在不同的表上第一次或第二次工作,但我有兩個表,我得到一個錯誤時試圖添加外鍵約束。 ,我得到的錯誤信息是:MySQL無法添加外鍵約束

ERROR 1215(HY000):無法添加外鍵約束

這是我用來創建表的SQL,這兩個問題的表是PatientAppointment

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.MedicalHistoryIDINT,Patient.MedicalHistory也需要是INT而不是SMALLINT

另外,在運行DDL之前,您應該運行查詢set foreign_key_checks=0,以便您可以以任意順序創建表,而不需要在相關子表之前創建所有父表。

+1

謝謝,數據類型不一致和foreign_key_checks修復了這個問題! – joshuaegclark 2013-03-20 21:53:29

+12

是由於我對錶格的排序不同,一個是UTF-8,另一個是latin1。 – 2015-07-23 22:01:03

+0

我跑了集foreign_key_checks = 0,但我仍然得到錯誤,因爲表的任意順序:( – JoeTidee 2016-02-05 12:21:56

14

嘗試使用相同類型的主鍵 - int(11) - 關於外鍵 - smallint(5) - 也是如此。

希望它有幫助!

+0

mysql>在foos上創建唯一索引index_bar_id(bar_id); ... mysql> alter table foos添加約束index_bar_id外鍵(bar_id)引用bars(id); http://sixarm.com/about/mysql-create-indexes-foreign-keys-constraints.html – CookieCoder 2013-12-17 16:09:16

3

檢查以下規則:

  • 首先檢查名是否給出正確的表名

  • 右二的數據類型給外鍵?

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 
); 
4

要設置一個外鍵表B必須在表A中設置關鍵

表A: INDEX idid

然後在表B,

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

我simil用兩個外鍵爲不同的表,但具有相同的鍵名稱的錯誤!我已更名密鑰和錯誤已經消失)

88

我已經設置了一個字段爲「未簽名」,而另一個沒有。一旦我將兩列設置爲Unsigned,它就可以工作。

+2

設置爲'unsigned'也適用於我。 – timothymarois 2017-02-16 14:35:12

+0

設置無符號的外鍵字段爲我工作 – manian 2017-05-30 14:24:45

0

有一個類似的錯誤,但在我的情況下,我錯過了將pk聲明爲auto_increment。

以防萬一它可幫助任何人

3

我有同樣的問題和解決方案是非常簡單的。 解決方案:在表中聲明的外鍵不應設置爲非空。

參考:如果指定SET NULL操作,請確保您沒有將子表中的列聲明爲NOT NULL。 (ref

4

請確保這兩個表均採用InnoDB格式。即使其中一個是MyISAM格式,那麼外鍵約束也不起作用。

此外,另一件事是,這兩個領域應該是相同的類型。如果一個是INT,那麼另一個也應該是INT。如果一個VARCHAR,其他的也應該是VARCHAR等

-1

我有同樣的問題,那麼我既父和子表中修正引擎名稱InnoDB和修正的參考字段名 外鍵(c_id)參考x9o_parent_tablec_id
然後它工作正常,表正確安裝。這將用於某人。

0

我得到了同樣的錯誤。原因在我的情況是:

  1. 我通過複製整個數據庫通過phpmyadmin創建了一個數據庫的備份。
  2. 我創建了一個新的數據庫,它具有與舊數據庫相同的名稱並選擇了它。
  3. 我啓動了一個SQL腳本來創建更新的表和數據。
  4. 我得到了錯誤。另外當我禁用foreign_key_checks。儘管數據庫完全是空的。

的原因是:由於我用phpMyAdmin來創建在重命名的數據庫的一些外鍵 - 在同一個數據庫名稱的前綴,但沒有更新的數據庫名稱前綴創建的外鍵。所以在backup-db中仍然有引用指向新創建的數據庫。

37
  • 引擎應該是相同的例如InnoDB
  • 數據類型應該是相同的,並且具有相同的長度。 例如VARCHAR(20)
  • 整理列字符集應該是相同的。 例如utf8
    注意:即使您的表格具有相同的整理,列仍可能有不同的整理。
  • 唯一 - 外鍵應該指參考表中唯一(通常是主鍵)的字段。
+1

最佳答案在嘗試幾乎所有事情後,事實證明,我必須明確地添加'唯一'到參考表列,即使它是一個'主鍵'! – Yahya 2017-11-14 11:18:11

1

我遇到了問題,並能夠通過確保數據類型完全匹配來解決它。

我正在使用SequelPro添加約束,並且默認情況下將主鍵設置爲無符號。

9

確認兩個表的字符編碼和排序規則是相同的。

在我自己的案例中,其中一個表使用的是utf8,另一個使用的是latin1

我有另一種情況,編碼是相同的,但排序規則不同。一個utf8_general_ci另一個utf8_unicode_ci

您可以運行此命令來設置表的編碼和排序規則。

ALTER TABLE tablename CONVERT TO CHARACTER SET utf8 COLLATE utf8_unicode_ci; 

我希望這可以幫助別人。

+0

不錯的@Adegoke,很好的答案 – 2016-06-30 16:57:21

0

我的解決方案也許有點尷尬,並告訴你爲什麼應該有時候看你有你的,而不是這些職位:)

我以前跑了正向工程,其中未能面前你的故事,所以這意味着我的數據庫已經有了幾張表格,然後我一直在試圖解決外鍵約束失敗的問題,試圖確保一切都是完美的,但是它在先前創建的表格上運行,所以它沒有成功。

0

檢查您的表格列上的簽名。如果引用表列是SIGNED,則引用的表列也應該SIGNED。這個錯誤的

0

另外一個原因是,當你的表或列包含保留keywords

有時一個不忘記這些。